YAML recipe guide
Build your own RF Swift image from a short YAML file: a base image, the packages you want and a few commands.
A YAML recipe describes a custom RF Swift image in a few lines: which image to start from, which packages to add and which commands to run. RF Swift turns it into a Dockerfile and builds the image for you.
Use a recipe when the official toolboxes miss a tool you need every time, or when a team should share one reproducible image. To add a single tool to one lab, Add more software is quicker.
Where to start: copy the first recipe below, build it, then look at the complete examples. The helper functions reference lists the build helpers you can call from a recipe.
Quick start
Your first recipe
Create a file named my-sdr.yaml:
base_image: "ubuntu:24.04"
tag: "my-sdr:latest"
packages:
- rtl-sdr
- gqrx-sdr
- hackrf
python_packages:
- numpy
- scipy
run_commands:
- "echo 'SDR tools installed successfully!'"Build it:
rfswift image build -r my-sdr.yamlYou now have a local image called my-sdr:latest. Create a lab from it like any other image: rfswift container create -i my-sdr:latest -n mylab.
Recipe fields
A recipe has two required fields and four optional ones.
| Field | Type | Required | What it does |
|---|---|---|---|
base_image |
String | Yes | The image to start from (for example ubuntu:24.04) |
tag |
String | Yes | Name and tag of the image you build |
packages |
List | No | System packages installed with APT |
python_packages |
List | No | Python packages installed with pip |
run_commands |
List | No | Bash commands run during the build |
context |
String | No | Build context directory (default: .) |
Here is every field in one file:
# Base configuration (required)
base_image: "ubuntu:24.04" # Base Docker image
tag: "my-image:latest" # Tag for the resulting image
# Package management (optional)
packages: # APT packages to install
- package1
- package2-dev
- package3
python_packages: # Python packages via pip
- numpy
- scipy==1.10.0 # Can specify versions
- git+https://github.com/user/repo.git # From git
# Custom commands (optional)
run_commands: # Bash commands to execute
- "echo 'Starting build...'"
- "mkdir -p /opt/tools"
- |
cmake_clone_and_build \
'https://github.com/osmocom/rtl-sdr.git' \
'build' \
'master' \
'' \
'rtlsdr_install'
# Build context (optional)
context: "." # Build context directory (default: ".")Choosing a base image
RF Swift base images
Starting from an RF Swift base image gives you its libraries and helper functions from the start:
# Core RF Swift base (recommended)
base_image: "penthertz/rfswift_resolute:core"
# RF Swift base image
base_image: "penthertz/rfswift_resolute:base"
# Ubuntu Jammy (22.04) - Stable LTS
base_image: "ubuntu:22.04"Standard base images
To build from scratch, start from a distribution image:
# Ubuntu (recommended for RF tools)
base_image: "ubuntu:24.04" # Noble Numbat (latest LTS)
base_image: "ubuntu:22.04" # Jammy Jellyfish (stable)
base_image: "ubuntu:20.04" # Focal Fossa (older but stable)
# Debian (alternative)
base_image: "debian:bookworm" # Debian 12 (latest stable)
base_image: "debian:bullseye" # Debian 11
# Fedora (for cutting-edge packages)
base_image: "fedora:39"
# Alpine (for minimal images)
base_image: "alpine:3.19" # Warning: May lack some RF librariesWhich base to pick
| Base | Pick it when |
|---|---|
| Ubuntu 24.04 | You want recent packages and wide hardware support, you build a general-purpose SDR image, or you are new to recipes |
| Ubuntu 22.04 | You need proven stability, long-term support, or you work in an enterprise environment |
| Debian | You prefer Debian’s package stability, want slightly less overhead than Ubuntu, or run Debian-based infrastructure |
| Alpine | Image size matters most (a base under 50 MB). Few RF libraries are packaged, so expect to compile a lot yourself |
Check the architecture
Make sure the base image exists for your target architecture (amd64, arm64 or riscv64). Multi-architecture images such as ubuntu:24.04 cover all three.
Installing packages
System packages (APT)
List system packages under packages. Comments help keep long lists readable:
packages:
# Development tools
- build-essential
- cmake
- git
- pkg-config
# Libraries
- libusb-1.0-0-dev
- libfftw3-dev
- libsoapysdr-dev
# SDR tools
- rtl-sdr
- hackrf
- gqrx-sdr
- gnuradio
# Utilities
- wget
- curl
- vimGood habits:
- Group related packages and label each group with a comment.
- Add the
-devpackage of every library you compile against. - List all build dependencies here, so they are installed before any compilation step in
run_commands.
Python packages (pip)
List Python packages under python_packages. You can pin versions, install from Git and request extras:
python_packages:
# Basic scientific stack
- numpy
- scipy
- matplotlib
# Specific versions
- "pandas==2.0.0"
- "scikit-learn>=1.3.0"
# From git repositories
- "git+https://github.com/pyrtlsdr/pyrtlsdr.git"
- "git+https://github.com/mossmann/hackrf.git@master#subdirectory=host/libhackrf/python"
# With extras
- "matplotlib[all]"
- "jupyter[notebook]"The version syntax is pip’s:
python_packages:
- "package" # Latest version
- "package==1.0.0" # Exact version
- "package>=1.0.0" # Minimum version
- "package>=1.0,<2.0" # Version rangeRunning commands (run_commands)
Everything under run_commands runs in Bash during the build, in order.
Simple commands
One command per line:
run_commands:
- "echo 'Build starting...'"
- "mkdir -p /opt/tools"
- "useradd -m rfuser"
- "chmod 755 /opt/tools"Multi-line commands
For several steps that belong together, use YAML’s pipe (|) syntax:
run_commands:
- |
echo "Installing custom tool..."
cd /opt
git clone https://github.com/user/tool.git
cd tool
make
make installHelper functions
RF Swift’s build helpers are available in every recipe. They print coloured messages, retry network steps, and clone and build CMake projects and GNU Radio out-of-tree modules:
run_commands:
# Colored output
- "colorecho 'Starting RTL-SDR installation...'"
# Install with retry logic
- "installfromnet 'git clone https://github.com/osmocom/rtl-sdr.git'"
# Build from source with CMake
- |
cmake_clone_and_build \
'https://github.com/osmocom/rtl-sdr.git' \
'build' \
'master' \
'' \
'rtlsdr_install' \
-DINSTALL_UDEV_RULES=ON
# GNU Radio OOT modules
- |
grclone_and_build \
'https://github.com/osmocom/gr-osmosdr.git' \
'gr-osmosdr' \
'gr_osmosdr_install'
# Success message
- "goodecho 'Installation complete!'"Every helper and its arguments are described in the helper functions reference.
Complete examples
Example 1: a simple SDR image
Basic SDR tools for learning and experimenting:
base_image: "ubuntu:24.04"
tag: "sdr-beginner:latest"
packages:
- rtl-sdr
- gqrx-sdr
- dump1090-mutability
- multimon-ng
python_packages:
- numpy
- matplotlib
run_commands:
- "echo 'SDR tools ready!'"Build it with rfswift image build -r sdr-beginner.yaml.
Example 2: a GNU Radio development environment
GNU Radio 3.10 built from source, with the gr-osmosdr out-of-tree module:
base_image: "ubuntu:24.04"
tag: "gnuradio-dev:3.10"
packages:
# GNU Radio dependencies
- git
- cmake
- g++
- libboost-all-dev
- libgmp-dev
- swig
- python3-numpy
- python3-mako
- python3-sphinx
- python3-lxml
- doxygen
- libfftw3-dev
- libsdl1.2-dev
- libgsl-dev
- libqwt-qt5-dev
- libqt5opengl5-dev
- python3-pyqt5
- liblog4cpp5-dev
- libzmq3-dev
# Additional tools
- vim
- git
- pkg-config
python_packages:
- numpy
- scipy
- matplotlib
run_commands:
# Build GNU Radio from source
- "colorecho 'Building GNU Radio 3.10...'"
- |
cmake_clone_and_build \
'https://github.com/gnuradio/gnuradio.git' \
'build' \
'v3.10.9.2' \
'v3.10.9.2' \
'gnuradio_install' \
-DCMAKE_BUILD_TYPE=Release \
-DENABLE_GR_QTGUI=ON \
-DENABLE_PYTHON=ON
# Build gr-osmosdr
- "colorecho 'Building gr-osmosdr...'"
- |
grclone_and_build \
'https://github.com/osmocom/gr-osmosdr.git' \
'gr-osmosdr' \
'gr_osmosdr_install'
- "goodecho 'GNU Radio environment ready!'"Example 3: several SDR devices
Drivers for RTL-SDR, HackRF, Airspy and LimeSDR, built from source:
base_image: "ubuntu:24.04"
tag: "multi-sdr:latest"
packages:
# Build essentials
- build-essential
- cmake
- git
- pkg-config
- libusb-1.0-0-dev
# Libraries
- libfftw3-dev
- libsoapysdr-dev
# Pre-built tools
- gqrx-sdr
python_packages:
- numpy
- scipy
- pyrtlsdr
run_commands:
# RTL-SDR
- "colorecho 'Installing RTL-SDR support...'"
- |
cmake_clone_and_build \
'https://github.com/osmocom/rtl-sdr.git' \
'build' \
'master' \
'' \
'rtlsdr_install' \
-DINSTALL_UDEV_RULES=ON \
-DDETACH_KERNEL_DRIVER=ON
# HackRF
- "colorecho 'Installing HackRF support...'"
- |
cmake_clone_and_build \
'https://github.com/mossmann/hackrf.git' \
'host/build' \
'master' \
'' \
'hackrf_install' \
-DINSTALL_UDEV_RULES=ON
# Airspy
- "colorecho 'Installing Airspy support...'"
- |
cmake_clone_and_build \
'https://github.com/airspy/airspyone_host.git' \
'build' \
'master' \
'' \
'airspy_install' \
-DINSTALL_UDEV_RULES=ON
# LimeSDR (via SoapySDR)
- "colorecho 'Installing LimeSDR support...'"
- |
cmake_clone_and_build \
'https://github.com/myriadrf/LimeSuite.git' \
'builddir' \
'master' \
'' \
'limesdr_install'
- "goodecho 'All SDR devices supported!'"Example 4: Bluetooth analysis tools
The BlueZ stack, Ubertooth and Python tools for Bluetooth work:
base_image: "ubuntu:24.04"
tag: "bluetooth-tools:latest"
packages:
# Bluetooth stack
- bluez
- bluez-tools
- bluetooth
- libbluetooth-dev
# Build tools
- build-essential
- cmake
- git
- libusb-1.0-0-dev
# Analysis tools
- wireshark-common
- tcpdump
python_packages:
- pybluez
- scapy
run_commands:
# Ubertooth tools
- "colorecho 'Installing Ubertooth...'"
- |
cmake_clone_and_build \
'https://github.com/greatscottgadgets/ubertooth.git' \
'host/build' \
'master' \
'' \
'ubertooth_install'
# Install additional Python tools
- "pip3install crackle"
- "goodecho 'Bluetooth tools ready!'"Example 5: an RF assessment toolkit
SDR, analysis and YARD Stick One tools on top of the RF Swift core image:
base_image: "penthertz/rfswift_resolute:core"
tag: "rf-hacking:latest"
packages:
# SDR tools
- gqrx-sdr
- inspectrum
- urh
# RF utilities
- kalibrate-rtl
- multimon-ng
- dump1090-mutability
# Analysis
- wireshark
- audacity
python_packages:
- numpy
- scipy
- matplotlib
- jupyter
- rfcat
run_commands:
# Universal Radio Hacker with dependencies
- "colorecho 'Setting up Universal Radio Hacker...'"
- "pip3install pyqt5 numpy psutil cython"
# Install YardStick One tools
- "colorecho 'Installing RfCat for YardStick One...'"
- "pip3install git+https://github.com/atlas0fd00m/rfcat.git"
# Create workspace
- "mkdir -p /root/rf-projects"
- "goodecho 'RF Hacking suite ready!'"Advanced techniques
Keeping the image small
Build in /tmp, then delete sources and APT caches at the end:
base_image: "ubuntu:24.04"
tag: "optimized-sdr:latest"
packages:
- build-essential
- cmake
- libusb-1.0-0-dev
run_commands:
# Build in /tmp for cleanup
- "cd /tmp"
# Build RTL-SDR
- |
cmake_clone_and_build \
'https://github.com/osmocom/rtl-sdr.git' \
'build' \
'master' \
'' \
'rtlsdr_install'
# Cleanup to reduce image size
- "rm -rf /tmp/*"
- "apt-get clean"
- "rm -rf /var/lib/apt/lists/*"Different steps per architecture
Test uname -m to run architecture-specific steps:
base_image: "ubuntu:24.04"
tag: "arch-specific:latest"
run_commands:
# Build different components based on architecture
- |
if [ "$(uname -m)" = "aarch64" ]; then
colorecho "Building for ARM64..."
# ARM-specific optimizations
else
colorecho "Building for x86_64..."
# x86-specific optimizations
fiPinning versions for reproducible builds
Pin APT and pip versions, and pass a commit to the build helper (fourth argument of cmake_clone_and_build):
base_image: "ubuntu:24.04"
tag: "reproducible-sdr:v1.0.0"
packages:
- rtl-sdr=0.6.0-1
- hackrf=2021.03.1-2
python_packages:
- "numpy==1.24.3"
- "scipy==1.10.1"
- "matplotlib==3.7.1"
run_commands:
# Pin a specific git commit (fourth argument)
- |
cmake_clone_and_build \
'https://github.com/osmocom/rtl-sdr.git' \
'build' \
'master' \
'a1b2c3d4e5f6' \
'rtlsdr_install'Environment variables
Append export lines to the shell profile:
base_image: "ubuntu:24.04"
tag: "custom-env:latest"
run_commands:
# Set environment variables
- "echo 'export PATH=/opt/tools/bin:$PATH' >> /root/.bashrc"
- "echo 'export LD_LIBRARY_PATH=/opt/tools/lib:$LD_LIBRARY_PATH' >> /root/.bashrc"
- "echo 'export PYTHONPATH=/opt/tools/python:$PYTHONPATH' >> /root/.bashrc"Building your recipe
Build commands
# Build with default settings
rfswift image build -r my-recipe.yaml
# Build without cache (fresh build)
rfswift image build -r my-recipe.yaml --no-cache
# Override tag from command line
rfswift image build -r my-recipe.yaml -t custom-tag:latestOptions
rfswift image build [options]
Options:
-r, --recipe string Path to YAML recipe file (default "rfswift-recipe.yaml")
-t, --tag string Override tag from recipe
--no-cache Build without using cache
-h, --help Help for build commandWhat happens during a build
When you run rfswift image build -r recipe.yaml, RF Swift:
- checks the YAML structure;
- generates a Dockerfile from it;
- prepares the build context;
- runs the Docker build;
- tags the resulting image;
- removes its temporary files.
Good practices
Keep recipes organised
Group packages by purpose and comment each group:
# Good: Organized and commented
base_image: "ubuntu:24.04"
tag: "my-sdr:v1.0"
packages:
# Build dependencies
- build-essential
- cmake
# SDR libraries
- libusb-1.0-0-dev
- libfftw3-dev
# SDR tools
- rtl-sdr
- gqrx-sdr
python_packages:
# Scientific computing
- numpy
- scipy
# SDR-specific
- pyrtlsdr
run_commands:
- "colorecho 'Build starting...'"
- "goodecho 'Build complete!'"Keep recipes in Git
Version your recipes and tag releases, so a team can rebuild the same image later:
# Store recipes in git
git add recipes/
git commit -m "Add SDR recipe v1.0"
git tag recipe-sdr-v1.0
# Share with team
git push origin main --tagsTest before you share
Build under a test tag, create a lab from it and check the tools:
# Build locally
rfswift image build -r test-recipe.yaml -t test:dev
# Test the image
rfswift container create -i test:dev -n test-container
# Verify tools work
rfswift container shell -c test-containerDocument the recipe
A short header says what the recipe is for and what it was tested with:
# SDR Analysis Container v1.2
# Author: Your Name
# Purpose: General purpose SDR analysis with RTL-SDR and HackRF support
# Last updated: 2024-01-12
base_image: "ubuntu:24.04"
tag: "sdr-analysis:v1.2"
# Core SDR packages - tested with RTL-SDR V3 and HackRF One
packages:
- rtl-sdr
- hackrf
# Python stack for signal processing
python_packages:
- numpy>=1.24.0 # Required for scipy
- scipy>=1.10.0 # Signal processingTroubleshooting
“Package not found”
The package name is wrong, or the package does not exist in the base image’s repositories. Check the exact name for that distribution:
# Problem: Package name incorrect or not available
packages:
- rtl-sdr-tools # Wrong name
# Solution: Use correct package name
packages:
- rtl-sdrA Python package fails to install
It usually needs system libraries that are missing. Install them under packages first:
# Problem: Missing system dependencies
python_packages:
- matplotlib # Needs system libraries
# Solution: Install system dependencies first
packages:
- python3-dev
- libfreetype6-dev
- libpng-dev
python_packages:
- matplotlib“Command not found” in run_commands
The helper functions are always available, so this is almost always a syntax error. Check the quoting and the line continuations:
# Problem: Helper functions not available
run_commands:
- "cmake_clone_and_build ..." # Fails
# Solution: They're automatically available - check syntax
run_commands:
- |
cmake_clone_and_build \
'https://...' \
'build' \
'master' \
'' \
'install_name'Checking a recipe before a long build
There is no dry-run flag yet. Check the YAML syntax, then build into a throwaway tag:
# Check YAML syntax
python3 -c "import yaml; yaml.safe_load(open('recipe.yaml'))"
# There is no dry-run flag yet: build into a throwaway tag to validate
rfswift image build -r recipe.yaml -t recipe-check:testDebugging a failing build
Rebuild with full output, or try the recipe’s commands by hand in a plain lab:
# Build with verbose output
docker build --progress=plain -t test:debug .
# Check generated Dockerfile
# (RF Swift generates it in /tmp during build)
# Interactive debugging
rfswift container create -i ubuntu:24.04 -n debug
# Manually test commands from recipeSharing recipes
A small Git repository, organised by category, is enough to share recipes with a team or the community:
# Create a recipe repository
mkdir rf-swift-recipes
cd rf-swift-recipes
# Organize by category
mkdir -p sdr bluetooth wifi automotive
# Add README with usage instructions
cat > README.md << 'EOF'
# RF Swift Recipe Collection
## SDR Recipes
- `sdr/rtlsdr-basic.yaml` - Basic RTL-SDR setup
- `sdr/multi-hardware.yaml` - Multiple SDR support
## Usage
```bash
rfswift image build -r sdr/rtlsdr-basic.yaml
```
EOF
# Share on GitHub
git init
git add .
git commit -m "Initial recipe collection"
git remote add origin https://github.com/yourusername/rf-swift-recipes.git
git push -u origin mainWhere to find and share recipes:
- the official RF Swift recipes;
- the RF Swift recipe repository, which accepts contributions;
- the Discord community.
Start with a small recipe and grow it: build, test, then add the next tool.