run
rfswift container create (run)
Create and start a new container from an RF Swift image, or, with --engine nix, a native Nix environment.
rfswift container create. The legacy form rfswift run and the short aliases rfswift create and rfswift new still work and print a notice. Flags are identical on every spelling; the examples below use the short legacy form for brevity.Synopsis
rfswift container create -i IMAGE -n CONTAINER_NAME [options]
rfswift run -i IMAGE -n CONTAINER_NAME [options] # legacy spelling
rfswift container create --engine nix -i ENVIRONMENT -n NAME [--lazy] [--pure] [--isolate] [--flake REF] [--create-only]The command pulls the image if it is not local, checks that the engine can map the devices you asked for (and says which it cannot, with the reason, before dropping them on your confirmation), checks USB reachability, creates the container with a workspace, and enters it with an interactive shell. On Windows it offers the usbipd device picker when it detects RF hardware.
-i and -n flags in an interactive terminal, RF Swift launches a guided wizard that walks you through all options step by step. See Interactive Wizard below.Options
Required Flags
| Flag | Description | Example |
|---|---|---|
-i, --image STRING |
Image name or tag to use | -i sdr_full |
-n, --name STRING |
Name for the new container | -n my_container |
Security Options
| Flag | Description | Default | Example |
|---|---|---|---|
-u, --privileged INT |
Privilege level (1=privileged, 0=unprivileged). Never required for USB devices | 0 |
-u 0 |
-a, --capabilities STRING |
Additional capabilities (comma-separated) | None | -a NET_ADMIN,NET_RAW |
-g, --cgroups STRING |
Cgroup device rules (comma-separated) | See config | -g "c 189:* rwm" |
-m, --seccomp STRING |
Custom seccomp profile path | Default | -m /path/to/profile.json |
Performance Options
| Flag | Description | Default | Example |
|---|---|---|---|
--realtime |
Enable realtime mode for SDR operations | false |
--realtime |
--ulimits STRING |
Set custom ulimits (comma-separated) | None | --ulimits "rtprio=95,memlock=-1" |
--gpus STRING |
GPU devices to pass through | None | --gpus all or --gpus 0,1 |
Workspace Options
| Flag | Description | Default | Example |
|---|---|---|---|
--workspace STRING |
Custom workspace host path | ~/rfswift-workspace/<name>/ |
--workspace ~/my-project |
--cwd |
Mount current directory as workspace | false | --cwd |
--no-workspace |
Disable automatic workspace | false | --no-workspace |
By default, every container gets a shared workspace directory automatically mounted:
- Host:
~/rfswift-workspace/<container-name>/ - Container:
/workspace
Files saved to /workspace inside the container are immediately available on the host. IQ captures, logs, reports and scripts all land in one place, without manual --bind flags.
Device & Volume Options
| Flag | Description | Example |
|---|---|---|
-s, --devices STRING |
Device mappings (comma-separated) | -s /dev/ttyUSB0:/dev/ttyUSB0 |
-b, --bind STRING |
Extra volume bindings (comma-separated) | -b ~/projects:/root/projects |
Network Options
| Flag | Description | Default | Example |
|---|---|---|---|
-t, --network STRING |
Network mode | host |
-t bridge |
-z, --exposedports STRING |
Expose ports for inter-container communication | None | -z 8080,3000 |
-w, --bindedports STRING |
Bind ports to host | None | -w 8080:80/tcp |
-x, --extrahosts STRING |
Add extra host entries | None | -x pluto.local:192.168.1.2 |
Display & Audio Options
| Flag | Description | Default | Example |
|---|---|---|---|
-d, --display STRING |
X11 display setting | DISPLAY=:0 |
-d DISPLAY=:1 |
-p, --pulseserver STRING |
PulseAudio server address | tcp:127.0.0.1:34567 |
-p tcp:127.0.0.1:4713 |
--no-x11 |
Disable X11 forwarding and remove X11 socket binding | false | --no-x11 |
--desktop |
Enable remote desktop via VNC/noVNC | false | --desktop |
--desktop-config STRING |
Desktop config as proto:host:port |
http:127.0.0.1:6080 |
--desktop-config "http:0.0.0.0:6080" |
--desktop-pass STRING |
Set VNC password for desktop access | None | --desktop-pass "mypassword" |
--desktop-ssl |
Enable SSL/TLS for desktop connections | false | --desktop-ssl |
Profile Options
| Flag | Description | Example |
|---|---|---|
--profile STRING |
Use a preset profile | --profile sdr-full |
Profiles bundle image, network, features, devices, ports, capabilities, and cgroup rules into a single named preset. CLI flags override profile values. See rfswift profile for details.
# Use a profile
rfswift run --profile sdr-full -n my_sdr
# Profile with CLI overrides
rfswift run --profile wifi -n my_wifi -t nat --realtimeVPN Options
| Flag | Description | Example |
|---|---|---|
--vpn STRING |
Enable VPN inside container | --vpn tailscale |
Format: --vpn TYPE[:ARGUMENT]
| Type | Argument | Example |
|---|---|---|
wireguard |
Config file path (required) | --vpn wireguard:./wg0.conf |
openvpn |
Config file path (required) | --vpn openvpn:./client.ovpn |
tailscale |
Auth key (optional) | --vpn tailscale or --vpn tailscale:tskey-auth-xxx |
netbird |
Setup key (optional) | --vpn netbird or --vpn netbird:nb-setup-xxx |
-u 1. Tailscale and Netbird work without privileges (userspace mode with SOCKS5 proxy). See VPN Inside Containers for details.Recording Options
| Flag | Description | Example |
|---|---|---|
--record |
Enable session recording | --record |
--record-output STRING |
Custom recording filename | --record-output session.cast |
Shell
| Flag | Description | Default | Example |
|---|---|---|---|
-e, --command STRING |
Shell or command to run in the container | /bin/zsh (Bash when zsh is missing) |
-e /bin/bash, -e "gnuradio-companion" |
Nix engine options (--engine nix)
| Flag | Description |
|---|---|
--lazy |
On-demand environment: each tool builds the first time it is called and is then pinned |
--pure |
Pure shell (nix develop --ignore-environment) |
--isolate |
Enter inside a jail (bubblewrap on Linux, Seatbelt on macOS): hides $HOME and the host filesystem, keeps USB and serial devices, the display and the network. Stored on the environment |
--flake REF |
Flake reference instead of the default (a local RF-Swift-nix checkout or github:PentHertz/RF-Swift-nix) |
--rebuild |
Force re-realisation of the closure at creation |
--create-only |
Create and realise without entering (scripts, the Workbench) |
With the Nix engine the workspace, --cwd, --no-workspace, --record, -e and the wizard behave as for containers; container-only flags (devices, capabilities, ports, desktop, VPN) do not apply. See the Nix engine guide.
Examples
Basic Usage
Create a simple SDR container:
rfswift container create -i sdr_full -n my_sdr
rfswift run -i sdr_full -n my_sdr # same, legacy spellingCreate a native Nix environment instead:
rfswift container create --engine nix -i sdr_light -n radio
rfswift container create --engine nix -i rfid -n badge --lazy --isolateCreate with default image from config:
# Requires imagename set in ~/.config/rfswift/config.ini
rfswift run -n my_containerWith Realtime Mode
Create container optimized for SDR operations:
rfswift run -i sdr_full -n sdr_realtime --realtimeThis automatically configures:
SYS_NICEcapabilityrtprio=95ulimitmemlock=unlimitedulimitnice=40ulimit
With custom ulimits:
rfswift run -i sdr_full -n custom_limits --ulimits "rtprio=95,memlock=-1,nofile=65536"Combine realtime with custom overrides:
rfswift run -i sdr_full -n sdr_pro --realtime --ulimits "rtprio=99"Professional SDR setup with all optimizations:
rfswift run -i sdr_full -n rf_pentest \
--realtime \
-s /dev/bus/usb:/dev/bus/usb \
-g "c 189:* rwm" \
-b ~/captures:/root/captures \
--recordWith Profiles
Quick container from a profile:
rfswift run --profile sdr-full -n my_sdrProfile with image override:
rfswift run --profile wifi -n wifi_custom -i penthertz/rfswift_resolute:sdr_fullProfile with NAT isolation:
rfswift run --profile pentest-full -n pentest_sessionWith Devices
All USB devices:
rfswift run -i sdr_full -n rtlsdr_work \
-s /dev/bus/usb:/dev/bus/usb \
-g "c 189:* rwm"Multiple USB serial devices:
rfswift run -i hardware -n multi_device \
-s /dev/ttyUSB0:/dev/ttyUSB0,/dev/ttyACM0:/dev/ttyACM0 \
-g "c 189:* rwm,c 166:* rwm"With Security Configuration
Unprivileged container with specific capabilities:
rfswift run -i wifi -n wifi_scan \
-u 0 \
-a NET_ADMIN,NET_RAW \
-t bridgeWith custom seccomp profile:
rfswift run -i pentest -n secure_assessment \
-u 0 \
-m ~/seccomp-profiles/restricted.json \
-g "c 189:* rwm"Privileged mode (use sparingly):
rfswift run -i hardware -n hardware_debug \
-u 1With Network Configuration
Bridge network with port binding:
rfswift run -i web_tools -n web_server \
-t bridge \
-w 8080:80/tcpMultiple ports exposed and bound:
rfswift run -i api_server -n backend \
-t bridge \
-z 3000,3001,3002 \
-w 8080:3000/tcp,8081:3001/tcpNetwork isolation (no network):
rfswift run -i analysis -n offline_analysis \
-t none \
-b ~/data:/root/dataCustom host entries:
rfswift run -i penthertz/rfswift_resolute:telecom -n network_test \
-x "device1.local:192.168.1.10,device2.local:192.168.1.11"With Session Recording
Record with auto-generated filename:
rfswift run -i bluetooth -n bt_assessment \
--recordRecord with custom filename:
rfswift run -i sdr_full -n client_pentest \
--record \
--record-output client-assessment-2024-01-12.castCombined: Recording with security and devices:
rfswift run -i wifi -n wifi_audit \
-u 0 \
-a NET_ADMIN,NET_RAW \
-t bridge \
-s /dev/wlan0:/dev/wlan0 \
--record \
--record-output wifi-audit-session.castWith Remote Desktop
Enable noVNC desktop (browser-based GUI):
rfswift run -i sdr_full -n sdr_desktop --desktopThen open http://127.0.0.1:6080 in your browser to access the GUI desktop.
Expose desktop on all interfaces:
rfswift run -i sdr_full -n sdr_desktop \
--desktop --desktop-config "http:0.0.0.0:6080"Use raw VNC instead of noVNC:
rfswift run -i sdr_full -n sdr_desktop \
--desktop --desktop-config "vnc::5900"Then connect with a VNC client (e.g., TigerVNC, RealVNC) to 127.0.0.1:5900.
Custom port:
rfswift run -i sdr_full -n sdr_desktop \
--desktop --desktop-config "http:0.0.0.0:8080"With VNC password (recommended when exposing on network):
rfswift run -i sdr_full -n sdr_desktop \
--desktop --desktop-config "http:0.0.0.0:6080" \
--desktop-pass "mysecretpass"Desktop with SDR devices and no X11 forwarding:
rfswift run -i sdr_full -n sdr_desktop \
--desktop \
--desktop-config "http:0.0.0.0:6080" \
--desktop-pass "mysecretpass" \
-s /dev/bus/usb:/dev/bus/usb \
-g "c 189:* rwm" \
--no-x11With VPN
Tailscale mesh (interactive login):
rfswift run -i sdr_full -n mesh_sdr --vpn tailscaleTailscale with auth key (headless):
rfswift run -i sdr_full -n mesh_sdr \
--vpn tailscale:tskey-auth-xxxxxxxxxxxxWireGuard tunnel (requires privileged mode):
rfswift run -i sdr_full -n vpn_sdr \
-u 1 \
--vpn wireguard:./wg0.confOpenVPN with bridge network:
rfswift run -i sdr_full -n corp_sdr \
-u 1 \
-t bridge \
--vpn openvpn:./client.ovpnNetbird mesh (interactive login):
rfswift run -i sdr_full -n nb_sdr --vpn netbirdVPN + Remote Desktop + SDR (full remote setup):
rfswift run -i sdr_full -n remote_sdr \
-u 1 \
--vpn tailscale \
--desktop --desktop-config "http:0.0.0.0:6080" \
-s /dev/bus/usb:/dev/bus/usb \
-g "c 189:* rwm" \
--recordComplex Real-World Examples
Complete SDR assessment setup:
rfswift run -i sdr_full -n site_survey \
-u 0 \
--realtime \
-s /dev/bus/usb:/dev/bus/usb \
-b /pathto/captures:/root/captures \
-b /pathto/projects:/root/projects:ro \
-g "c 189:* rwm,c 116:* rwm" \
-t bridge \
-w 8080:80/tcp \
--record \
--record-output site-survey-2024-01-12.castBluetooth security assessment:
rfswift run -i bluetooth -n bt_pentest \
-u 0 \
-a NET_ADMIN,NET_RAW \
-s /dev/ttyACM0:/dev/ttyACM0 \
-b /pathto/bt-captures:/root/captures \
-g "c 166:* rwm" \
-t bridge \
--recordHigh-performance signal capture:
rfswift run -i sdr_full -n high_perf_capture \
--realtime \
-s /dev/bus/usb:/dev/bus/usb \
-g "c 189:* rwm" \
-b ~/captures:/root/capturesDetailed Option Explanations
Image Selection (-i, --image)
Specifies which RF Swift image to use for the container.
Formats:
# Full registry path
-i penthertz/rfswift_resolute:sdr_full
# Short name (resolves to penthertz/rfswift_resolute:IMAGE)
-i sdr_full
# Custom registry
-i myregistry.com/rfswift:customCommon images:
sdr_full- Complete SDR toolkitsdr_light- Lightweight SDR toolsbluetooth- Bluetooth security toolswifi- Wi-Fi assessment toolshardware- Hardware hacking toolsautomotive- Vehicle protocol tools
See List of Images for all available images.
Container Naming (-n, --name)
Assigns a unique name to the container. Names must be unique across all containers (running or stopped).
Naming conventions:
# Good names (descriptive, unique)
-n rtlsdr_capture_session_1
-n client_assessment_2024_01
-n wifi_audit_conference_room
-n bluetooth_pentest_device_a
# Avoid generic names
-n test # Too generic
-n container1 # Not descriptiveRealtime Mode (--realtime)
Enables optimized settings for low-latency SDR operations. This is a convenience flag that automatically configures:
| Setting | Value | Purpose |
|---|---|---|
| SYS_NICE capability | Added | Allows real-time scheduling |
| rtprio ulimit | 95 | Enables chrt -f 1 through chrt -f 95 |
| memlock ulimit | unlimited | Prevents sample buffers from being swapped |
| nice ulimit | 40 | Allows nice -20 to +19 |
When to use:
- High sample rate captures (avoid buffer underruns)
- Real-time signal processing with GNU Radio, SDR++, GQRX
- Time-critical protocols (RFID, NFC, automotive)
- Professional pentesting where reliability is critical
# Simple usage
rfswift run -i sdr_full -n sdr_work --realtime
# Verify inside container
rfswift exec -c sdr_work -e "ulimit -r"
# Output: 95
# Use real-time scheduling
rfswift exec -c sdr_work
chrt -f 50 rtl_sdr -f 433920000 -s 2048000 output.binGPU Passthrough (--gpus)
Passes GPU devices into the container for hardware-accelerated workloads. Requires the appropriate GPU runtime (NVIDIA Container Toolkit, ROCm, etc.) installed on the host.
| Specifier | Meaning |
|---|---|
all |
All available GPUs |
0 |
First GPU only |
0,1 |
First and second GPU |
# All GPUs
rfswift run -i sdr_full -n gpu_sdr --gpus all
# Specific GPU
rfswift run -i sdr_full -n gpu_sdr --gpus 0
# Combined with other features
rfswift run -i sdr_full -n gpu_sdr --gpus all --realtime --desktopSee gpus for full documentation, prerequisites, and troubleshooting.
Custom Ulimits (--ulimits)
Set specific resource limits for fine-grained control.
Format: name=value or name=soft:hard (comma-separated for multiple)
| Name | Description | Example |
|---|---|---|
rtprio |
Real-time scheduling priority (0-99) | rtprio=95 |
memlock |
Max locked memory (-1 = unlimited) | memlock=-1 |
nice |
Nice priority range | nice=40 |
nofile |
Max open file descriptors | nofile=65536 |
nproc |
Max processes | nproc=4096 |
Examples:
# Single ulimit
--ulimits "rtprio=95"
# Multiple ulimits
--ulimits "rtprio=95,memlock=-1,nofile=65536"
# With soft:hard format
--ulimits "nofile=1024:65536"
# Combine with realtime (custom values override defaults)
--realtime --ulimits "rtprio=99"Privilege Level (-u, --privileged)
Controls container privilege level:
0(default): Unprivileged - Recommended for most use cases1: Privileged - Full host access, use only when necessary
When to use privileged mode:
- Kernel module loading required
- Low-level hardware access
- Complex network operations
-u 1 only when absolutely necessary and remove the container after use.Capabilities (-a, --capabilities)
Add specific Linux capabilities for fine-grained privilege control.
Common capabilities:
# Network operations
-a NET_ADMIN,NET_RAW
# Process debugging
-a SYS_PTRACE
# Real-time scheduling (added automatically with --realtime)
-a SYS_NICE
# Low port binding
-a NET_BIND_SERVICE
# File ownership changes
-a CHOWN,DAC_OVERRIDESee Capabilities Reference for complete list.
Cgroups (-g, --cgroups)
Control which device types the container can access.
Format: type major:minor permissions
type:c(character) orb(block)major:minor: Device numbers (use*for all)permissions:r(read),w(write),m(mknod)
Common rules:
# USB serial (RTL-SDR, HackRF)
-g "c 189:* rwm"
# ACM devices (Proxmark3, Arduino)
-g "c 166:* rwm"
# USB converters
-g "c 188:* rwm"
# Audio devices
-g "c 116:* rwm"
# GPU devices
-g "c 226:* rwm"
# Multiple devices
-g "c 189:* rwm,c 166:* rwm,c 188:* rwm"Find device major numbers:
ls -l /dev/your_device
# Example output: crw-rw---- 1 root dialout 189, 0 ...
# ^^^ major numberDevice Mappings (-s, --devices)
Make specific host devices available in the container. Serial ports (/dev/ttyACM*, /dev/ttyUSB*, /dev/ttyAMA*) named here are hot-pluggable on Docker and rootful Podman: plugged in at creation they are mapped, absent they are attached on demand when you plug them in and open a shell. Before creation RF Swift lists the devices this engine cannot map on your host (rootless Podman root-only nodes, a device absent from the Lima VM, USB on Docker Desktop for macOS) and asks once before dropping them.
Format: host_device:container_device or just host_device (same path in container)
# Single device
-s /dev/ttyUSB0:/dev/ttyUSB0
# Multiple devices
-s /dev/ttyUSB0:/dev/ttyUSB0,/dev/ttyACM0:/dev/ttyACM0/dev/bus/usb mapping with c 189:* rwm is what makes a device reachable; a bind mount alone lists the nodes but cannot open them, and --privileged is not required. RF Swift checks this before creating the container.Volume Bindings (-b, --bind)
Share directories between host and container.
Format: host_path:container_path[:options]
Options:
- None (default): Read-write access
:ro: Read-only access
# Read-write binding
-b ~/projects:/root/projects
# Read-only binding
-b ~/samples:/root/samples:ro
# Multiple bindings
-b ~/projects:/root/projects,~/captures:/root/capturesUse cases:
- Share project files
- Save captures to host
- Mount firmware samples (read-only)
- Share tool configurations
Network Modes (-t, --network)
Configure container network isolation:
| Mode | Description | Use Case |
|---|---|---|
host |
No isolation (default) | Most RF tools, full network access |
nat |
Isolated NAT network (RF Swift managed) | Pentesting, desktop mode, network isolation |
nat:NAME |
Join an existing NAT network | Multiple containers on same subnet |
bridge |
Default Docker bridge | Web services, API servers |
none |
No network access | Offline analysis, malware analysis |
container:NAME |
Share network with another container | Linked services |
# Full network access (default)
-t host
# Isolated NAT network (auto-creates subnet)
-t nat
# Join existing NAT network
-t nat:rfswift_nat_mylab
# Isolated with port forwarding
-t bridge -w 8080:80/tcp
# Complete isolation
-t nonePort Configuration
Exposed ports (-z): Make ports available to other containers
-z 8080 # Single port
-z 8080,3000,3001 # Multiple portsBound ports (-w): Publish ports to host
# Format: host_port:container_port/protocol
-w 8080:80/tcp
# With host IP
-w 127.0.0.1:8080:80/tcp
# Multiple ports
-w 8080:80/tcp,8443:443/tcpDisplay Options
X11 Display (-d): Configure X11 forwarding for GUI applications
-d DISPLAY=:0 # Default display
-d DISPLAY=:1 # Alternate displayPulseAudio (-p): Configure audio server
-p tcp:127.0.0.1:34567 # Default
-p tcp:localhost:4713 # Custom portDisable X11 (--no-x11): Disables X11 forwarding and removes the /tmp/.X11-unix socket binding from the container for improved security.
--no-x11 # No X11 forwarding, no X11 socket bindingRemote Desktop (--desktop)
Enable a remote desktop inside the container, accessible via a web browser (noVNC) or a VNC client. This is useful for running GUI tools (SDR++, SDRangel, GQRX, etc.) without requiring X11 forwarding on the host.
When enabled, RF Swift:
- Injects
RFSWIFT_DESKTOP_PROTO,RFSWIFT_DESKTOP_HOST, andRFSWIFT_DESKTOP_PORTenvironment variables into the container - Uses an entrypoint wrapper that starts the VNC server before launching the shell
- Sets up port bindings automatically for non-host network modes
- Prints the access URL to the terminal
- Adds an
org.rfswift.desktoplabel to the container
Desktop config format (--desktop-config): proto:host:port
All parts are optional and fall back to defaults:
| Part | Options | Default |
|---|---|---|
proto |
http (noVNC), vnc (raw VNC) |
http |
host |
Bind address | 127.0.0.1 |
port |
Listen port | 6080 (http) or 5900 (vnc) |
# Browser access (default, localhost only)
--desktop
--desktop --desktop-config "http:0.0.0.0:6080"
# VNC client access
--desktop --desktop-config "vnc::5900"
# Custom port on all interfaces
--desktop --desktop-config "http:0.0.0.0:8080"Password protection (--desktop-pass):
Set a VNC password to secure the desktop session. Recommended when binding to 0.0.0.0:
# Password-protected desktop on all interfaces
--desktop --desktop-config "http:0.0.0.0:6080" --desktop-pass "mysecretpass"When a password is set, both noVNC (browser) and VNC clients will prompt for it before connecting. Without a password, access is unauthenticated. That is safe when bound to 127.0.0.1 (the default), but a security risk when exposed on the network.
SSL/TLS encryption (--desktop-ssl):
Enable SSL/TLS to encrypt the desktop connection. A self-signed certificate is automatically generated inside the container:
# SSL-encrypted desktop with password
--desktop --desktop-config "http:0.0.0.0:6080" --desktop-pass "mysecretpass" --desktop-ssl
# SSL with VNC client
--desktop --desktop-config "vnc:0.0.0.0:5900" --desktop-pass "mysecretpass" --desktop-sslWith SSL enabled, noVNC uses https:// and VNC clients connect via vncs:// (TLS-wrapped VNC). The self-signed certificate will trigger a browser warning on first connection, which is expected.
The password and SSL can also be set in the config file (~/.config/rfswift/config.ini):
[desktop]
password = mysecretpass
ssl = true--desktop with --no-x11 when you only need browser-based GUI access. This removes the X11 socket binding entirely, which improves security and avoids the need for xhost or X11 configuration on the host.Recording Options
Enable recording (--record): Records terminal session
--record # Auto-generated filenameCustom filename (--record-output): Specify recording filename
--record-output client-session.cast
--record-output /path/to/recordings/$(date +%Y%m%d)-session.castRecordings are saved in asciinema format (.cast files) and can be replayed with rfswift log replay.
Auto-generated filenames: When --record is used without --record-output, the filename is automatically generated as:
rfswift-run-{container_name}-{YYYYMMDD-HHMMSS}.castRecording indicator: During recording, the terminal title changes to ⏺ REC | RF Swift as a visual reminder. The environment variable RFSWIFT_RECORDING=1 is also set inside the container, which can be used by scripts to detect recording mode.
Interactive Wizard
When you run rfswift run without specifying -i (image) and -n (name) in an interactive terminal, RF Swift launches a step-by-step guided wizard using a TUI (Terminal User Interface).
Launch the wizard:
rfswift runWizard Steps
The wizard guides you through the following steps:
-
Profile Selection (if profiles are available) – Choose a profile to pre-fill settings, or select “No profile” for manual configuration. If a profile is selected, you’re asked whether to use it as-is (fast path: only asks for container name) or customize all settings with profile values pre-filled.
-
Image Selection – If a profile was selected, its image appears first with all local images available as alternatives, plus “Other (enter manually)”. Without a profile, shows a scrollable picker of local images.
-
Container Name – Required text input (placeholder:
my_sdr). -
Workspace Directory – Select how to mount the shared workspace:
- Auto (default):
~/rfswift-workspace/<name>/->/workspace - Custom path: Enter a host directory to mount as
/workspace - Current directory: Mount
$PWDas/workspace - Disable: No workspace mount
-
Volume Bindings – Asks if you want to add additional volume bindings beyond the workspace.
-
Device Mappings – Asks if you want to add device mappings, then prompts for comma-separated device paths.
-
Port Mappings – Simplified port binding step. Enter
hostPort:containerPortpairs (e.g.,8080:80,4443:443). RF Swift auto-generates both exposed ports and port bindings from this input. -
Network Mode – Select from host, NAT (create new isolated network), join existing NAT network, or bridge.
-
Feature Toggles – Multi-select checklist:
- Remote Desktop (VNC/noVNC)
- Desktop SSL/TLS
- Disable X11 forwarding
- Privileged mode
- Realtime mode (audio/SDR)
- VPN (WireGuard/OpenVPN/Tailscale/Netbird)
-
Desktop Port Configuration (if desktop enabled with non-host network) – Choose the host bind address (
127.0.0.1or0.0.0.0) and port for the desktop service. -
VPN Configuration (if VPN selected) – Prompts for VPN type, then type-specific input.
-
Capabilities – Multi-select from 18 common Linux capabilities with descriptions (NET_ADMIN, NET_RAW, SYS_RAWIO, SYS_ADMIN, SYS_PTRACE, SYS_NICE, etc.).
-
Cgroup Rules – Multi-select from common device cgroup rules with descriptions:
c 189:* rwm: USB devices (SDR dongles, serial adapters)c 188:* rwm: USB serial (ttyUSB)c 166:* rwm: ACM modems (ttyACM)c 116:* rwm: ALSA sound devicesc 226:* rwm: DRI/GPU renderingc 13:* rwm: Input devices (HID, joystick)c 137:* rwm: VHCI (virtual HCI for Bluetooth)- And more…
-
USB Devices (macOS with
--engine limaonly) – Asks whether to attach USB devices to the Lima VM, then shows a multi-select picker of discovered host USB devices. -
Configuration Recap – Displays a summary of all selected options, including workspace path.
-
CLI Equivalent – Shows the equivalent
rfswift runcommand. -
Final Confirmation –
Create this container?Yes/No prompt.
Example: Wizard with Profile (Fast Path)
? Start from a profile?
> sdr-full: Full SDR suite, realtime and USB hotplug
? Use profile 'sdr-full' as-is?
> Yes, use as-is
? Container name: my_sdr_work
──────────────────────────────────────────────────
Container Configuration (from profile):
Image: penthertz/rfswift_resolute:sdr_full
Name: my_sdr_work
Network: host
Realtime: enabled
──────────────────────────────────────────────────
? Create this container? YesExample: Wizard without Profile
? Start from a profile?
> No profile (manual configuration)
? Select an image:
> penthertz/rfswift_resolute:sdr_full
? Container name: my_sdr_work
? Add volume bindings? Yes
? Volume bindings: ~/captures:/root/captures
? Add device mappings? Yes
? Device paths: /dev/bus/usb
? Expose ports? No
? Network mode: Host
? Select features:
[x] Realtime mode (audio/SDR)
[x] VPN (WireGuard/OpenVPN/Tailscale/Netbird)
? VPN type: tailscale
? Auth key (optional):
? Add extra Linux capabilities? Yes
? Select capabilities:
[x] NET_ADMIN - network config, monitor mode, packet capture
[x] NET_RAW - raw sockets, packet injection
? Add device cgroup rules? Yes
? Select cgroup rules:
[x] c 189:* rwm - USB devices (SDR dongles, serial adapters)
──────────────────────────────────────────────────
Container Configuration:
Image: penthertz/rfswift_resolute:sdr_full
Name: my_sdr_work
Bindings: ~/captures:/root/captures
Devices: /dev/bus/usb
Capabilities: NET_ADMIN,NET_RAW
Cgroups: c 189:* rwm
Realtime: enabled
VPN: tailscale
──────────────────────────────────────────────────
Equivalent CLI command:
rfswift run -i penthertz/rfswift_resolute:sdr_full -n my_sdr_work \
-b ~/captures:/root/captures -s /dev/bus/usb \
-a NET_ADMIN,NET_RAW -g "c 189:* rwm" --realtime --vpn tailscale
? Create this container? Yes-i and -n flags explicitly.Common Patterns
Quick Container for Testing
# Minimal setup
rfswift run -i sdr_light -n test
# With one device
rfswift run -i sdr_full -n quick_test -s /dev/bus/usb:/dev/bus/usbHigh-Performance SDR Container
rfswift run -i sdr_full -n high_perf \
--realtime \
-s /dev/bus/usb:/dev/bus/usb \
-g "c 189:* rwm" \
-b ~/captures:/root/capturesRepeatable Assessment Container
# Save as script: setup_assessment.sh
#!/bin/bash
CONTAINER_NAME="assessment_$(date +%Y%m%d)"
rfswift run -i pentest -n "$CONTAINER_NAME" \
-u 0 \
--realtime \
-t bridge \
-b ~/assessments:/root/work \
--record \
--record-output "${CONTAINER_NAME}.cast"Development Container
rfswift run -i sdr_full -n sdr_dev \
-b ~/code:/root/code \
-b ~/.ssh:/root/.ssh:ro \
-b ~/.gitconfig:/root/.gitconfig:ro \
-w 8888:8888/tcpRemote Desktop SDR Workstation
rfswift run -i sdr_full -n remote_sdr \
--desktop \
--desktop-config "http:0.0.0.0:6080" \
--no-x11 \
--realtime \
-s /dev/bus/usb:/dev/bus/usb \
-g "c 189:* rwm" \
-b ~/captures:/root/captures \
--recordIsolated Analysis Container
rfswift run -i reversing -n isolated_analysis \
-u 0 \
-t none \
-b ~/samples:/root/samples:ro \
-b ~/output:/root/output \
--no-x11Troubleshooting
Container Name Already Exists
Error: container name 'X' is already in use. Use a different name with -n, or exec into the existing container with: rfswift exec -c X
Solution:
# Exec into the existing container
rfswift exec -c container_name
# Or remove it and recreate
rfswift remove -c container_name
# Or use a different name
rfswift run -i image -n container_name_2Image Not Found
Error: Error: No such image: penthertz/rfswift_resolute:image_name
Solution:
# Pull image first
rfswift images pull -i image_name
# Or let run pull automatically (if network available)
rfswift run -i image_name -n containerDevice Not Accessible
Problem: Device binding added but can’t access device in container
Solution:
# Add cgroup rule for device type
rfswift run -i image -n container \
-s /dev/ttyUSB0:/dev/ttyUSB0 \
-g "c 189:* rwm"
# Or add dynamically
rfswift config cgroups add -c container -r "c 189:* rwm"Permission Denied for Device
Problem: Permission denied when accessing device
Solution:
# Check host permissions
ls -l /dev/your_device
# Add user to device group on host
sudo usermod -aG dialout $USER
newgrp dialout
# Then run container
rfswift run -i image -n container -s /dev/your_device:/dev/your_deviceNetwork Operations Fail
Problem: Wi-Fi/Bluetooth tools can’t configure interfaces
Solution:
# Add network capabilities
rfswift run -i wifi -n wifi_tools \
-a NET_ADMIN,NET_RAW \
-t bridgeX11 Not Working
Problem: GUI applications won’t start or display
Solution:
# On host (Linux)
xhost +local:
# Then run container
rfswift run -i image -n container -d DISPLAY=$DISPLAY
# Or disable X11 for headless operation
rfswift run -i image -n container --no-x11Audio Not Working
Problem: No audio output from container
Solution:
# Enable audio support first
rfswift host audio enable
# Check PulseAudio is running
ps aux | grep pulse
# Run container with correct server
rfswift run -i image -n container -p tcp:127.0.0.1:34567Port Already in Use
Problem: Can’t bind port - already in use
Solution:
# Check what's using the port
sudo lsof -i :8080
# Use different host port
rfswift run -i image -n container -w 8081:80/tcp
# Or stop conflicting service
sudo systemctl stop service_nameBuffer Underruns with SDR
Problem: Experiencing sample drops or buffer underruns
Solution:
# Enable realtime mode
rfswift run -i sdr_full -n sdr_work --realtime
# Or add to existing container
rfswift realtime enable -c existing_container
# Verify inside container
rfswift exec -c sdr_work -e "ulimit -r"
# Should show: 95
# Use real-time scheduling
chrt -f 50 your_sdr_commandBest Practices
1. Use Descriptive Names
# Good
rfswift run -i sdr_full -n rtlsdr_spectrum_analysis_2024_01
# Not recommended
rfswift run -i sdr_full -n test12. Start Unprivileged
Always start with -u 0 and add capabilities as needed:
# Start unprivileged
rfswift run -i wifi -n wifi_scan -u 0
# Add capabilities if needed
rfswift config capabilities add -c wifi_scan -p NET_ADMIN3. Use Realtime Mode for SDR Work
# Always use --realtime for SDR captures
rfswift run -i sdr_full -n hackrf_capture --realtime4. Use Read-Only Mounts for Reference Data
rfswift run -i analysis -n data_analysis \
-b ~/samples:/root/samples:ro \
-b ~/output:/root/output5. Record Important Sessions
rfswift run -i pentest -n client_assessment \
--record \
--record-output client-$(date +%Y%m%d).cast6. Use Bridge Network for Services
rfswift run -i web_tools -n web_server \
-t bridge \
-w 127.0.0.1:8080:80/tcp7. Organize Project Directories
# Create organized structure
mkdir -p /pathto/rf-assessments/{captures,projects,recordings}
# Use in containers
rfswift run -i sdr_full -n assessment \
-b /pathto/rf-assessments/captures:/root/captures,/pathto/rf-assessments/projects:/root/projects \
--record-output /pathto/rf-assessments/recordings/session.castRelated Commands
profile- Manage container profiles (presets)exec- Enter an existing containerstop- Stop a running containerremove- Remove a containerbindings- Dynamically add devices/volumescapabilities- Modify capabilities after creationcgroups- Modify cgroup rules after creationports- Manage ports after creationrealtime- Enable/disable realtime mode on existing containersulimits- Manage ulimits on existing containers- VPN Inside Containers - Detailed VPN setup guide
- Using Podman - Podman-specific guidance
--realtime flag for optimal SDR performance. It automatically configures rtprio, memlock, nice ulimits and SYS_NICE capability to eliminate buffer underruns!rfswift run --help to see all options with their current default values from your config file.