run

rfswift run

Create and start a new container from an RF Swift image.

Synopsis

rfswift run -i IMAGE -n CONTAINER_NAME [options]

The run command is the primary way to create new containers in RF Swift. It pulls the specified image (if not already available), creates a container with the given name, and starts it with an interactive shell.

Interactive Wizard: When run without -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
Both flags are optional when using the interactive wizard. If omitted in an interactive terminal, the wizard launches automatically.

Security Options

Flag Description Default Example
-u, --privileged INT Privilege level (1=privileged, 0=unprivileged) 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"

Device & Volume Options

Flag Description Example
-s, --devices STRING Device mappings (comma-separated) -s /dev/ttyUSB0:/dev/ttyUSB0
-b, --bind STRING 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 --realtime

VPN 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
Privileged mode: WireGuard and OpenVPN require -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

Examples

Basic Usage

Create a simple SDR container:

rfswift run -i sdr_full -n my_sdr

Create with default image from config:

# Requires imagename set in ~/.config/rfswift/config.ini
rfswift run -n my_container

With Realtime Mode

Create container optimized for SDR operations:

rfswift run -i sdr_full -n sdr_realtime --realtime

This automatically configures:

  • SYS_NICE capability
  • rtprio=95 ulimit
  • memlock=unlimited ulimit
  • nice=40 ulimit

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 \
  --record

With Profiles

Quick container from a profile:

rfswift run --profile sdr-full -n my_sdr

Profile with image override:

rfswift run --profile wifi -n wifi_custom -i penthertz/rfswift_noble:sdr_full

Profile with NAT isolation:

rfswift run --profile pentest-full -n pentest_session

With 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 bridge

With 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 1

With Network Configuration

Bridge network with port binding:

rfswift run -i web_tools -n web_server \
  -t bridge \
  -w 8080:80/tcp

Multiple ports exposed and bound:

rfswift run -i api_server -n backend \
  -t bridge \
  -z 3000,3001,3002 \
  -w 8080:3000/tcp,8081:3001/tcp

Network isolation (no network):

rfswift run -i analysis -n offline_analysis \
  -t none \
  -b ~/data:/root/data

Custom host entries:

rfswift run -i penthertz/rfswift_noble: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 \
  --record

Record with custom filename:

rfswift run -i sdr_full -n client_pentest \
  --record \
  --record-output client-assessment-2024-01-12.cast

Combined: 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.cast

With Remote Desktop

Enable noVNC desktop (browser-based GUI):

rfswift run -i sdr_full -n sdr_desktop --desktop

Then 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-x11

With VPN

Tailscale mesh (interactive login):

rfswift run -i sdr_full -n mesh_sdr --vpn tailscale

Tailscale with auth key (headless):

rfswift run -i sdr_full -n mesh_sdr \
  --vpn tailscale:tskey-auth-xxxxxxxxxxxx

WireGuard tunnel (requires privileged mode):

rfswift run -i sdr_full -n vpn_sdr \
  -u 1 \
  --vpn wireguard:./wg0.conf

OpenVPN with bridge network:

rfswift run -i sdr_full -n corp_sdr \
  -u 1 \
  -t bridge \
  --vpn openvpn:./client.ovpn

Netbird mesh (interactive login):

rfswift run -i sdr_full -n nb_sdr --vpn netbird

VPN + 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" \
  --record

Complex 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.cast

Bluetooth 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 \
  --record

High-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/captures

Detailed Option Explanations

Image Selection (-i, --image)

Specifies which RF Swift image to use for the container.

Formats:

# Full registry path
-i penthertz/rfswift_noble:sdr_full

# Short name (resolves to penthertz/rfswift_noble:IMAGE)
-i sdr_full

# Custom registry
-i myregistry.com/rfswift:custom

Common images:

  • sdr_full - Complete SDR toolkit
  • sdr_light - Lightweight SDR tools
  • bluetooth - Bluetooth security tools
  • wifi - Wi-Fi assessment tools
  • hardware - Hardware hacking tools
  • automotive - 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 descriptive

Realtime 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.bin

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 cases
  • 1: Privileged - Full host access, use only when necessary

When to use privileged mode:

  • Kernel module loading required
  • Low-level hardware access
  • Complex network operations
Security Risk: Privileged containers can escape isolation and compromise the host. Use -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_OVERRIDE

See Capabilities Reference for complete list.

Cgroups (-g, --cgroups)

Control which device types the container can access.

Format: type major:minor permissions

  • type: c (character) or b (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 number

Device Mappings (-s, --devices)

Make specific host devices available in the container.

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
Cgroups + Devices: You need BOTH cgroup rules and device mappings. Cgroups allow access to device types, mappings make specific devices available.

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/captures

Use 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 none
NAT mode creates an isolated network with its own subnet. RF Swift automatically manages the network lifecycle. When using NAT with desktop mode, port bindings are configured automatically so you can access the desktop from your browser on the host.

Port Configuration

Exposed ports (-z): Make ports available to other containers

-z 8080              # Single port
-z 8080,3000,3001    # Multiple ports

Bound 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/tcp

Display Options

X11 Display (-d): Configure X11 forwarding for GUI applications

-d DISPLAY=:0        # Default display
-d DISPLAY=:1        # Alternate display

PulseAudio (-p): Configure audio server

-p tcp:127.0.0.1:34567    # Default
-p tcp:localhost:4713      # Custom port

Disable 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 binding

Remote 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, and RFSWIFT_DESKTOP_PORT environment 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.desktop label 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 — safe when bound to 127.0.0.1 (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-ssl

With 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 — this is expected.

The password and SSL can also be set in the config file (~/.config/rfswift/config.ini):

[desktop]
password = mysecretpass
ssl = true
Tip: Combine --desktop with --no-x11 when you only need browser-based GUI access — this removes the X11 socket binding entirely, improving security and avoiding the need for xhost or X11 configuration on the host.

Recording Options

Enable recording (--record): Records terminal session

--record    # Auto-generated filename

Custom filename (--record-output): Specify recording filename

--record-output client-session.cast
--record-output /path/to/recordings/$(date +%Y%m%d)-session.cast

Recordings 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}.cast

Recording 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 run

Wizard Steps

The wizard guides you through the following steps:

  1. 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.

  2. 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.

  3. Container Name – Required text input (placeholder: my_sdr).

  4. Volume Bindings – Asks if you want to add volume bindings, then prompts for comma-separated host:container paths.

  5. Device Mappings – Asks if you want to add device mappings, then prompts for comma-separated device paths.

  6. Port Mappings – Simplified port binding step. Enter hostPort:containerPort pairs (e.g., 8080:80,4443:443). RF Swift auto-generates both exposed ports and port bindings from this input.

  7. Network Mode – Select from host, NAT (create new isolated network), join existing NAT network, or bridge.

  8. 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)
  9. Desktop Port Configuration (if desktop enabled with non-host network) – Choose the host bind address (127.0.0.1 or 0.0.0.0) and port for the desktop service.

  10. VPN Configuration (if VPN selected) – Prompts for VPN type, then type-specific input.

  11. Capabilities – Multi-select from 18 common Linux capabilities with descriptions (NET_ADMIN, NET_RAW, SYS_RAWIO, SYS_ADMIN, SYS_PTRACE, SYS_NICE, etc.).

  12. 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 devices
    • c 226:* rwm — DRI/GPU rendering
    • c 13:* rwm — Input devices (HID, joystick)
    • c 137:* rwm — VHCI (virtual HCI for Bluetooth)
    • And more…
  13. Configuration Recap – Displays a summary of all selected options.

  14. CLI Equivalent – Shows the equivalent rfswift run command.

  15. Final ConfirmationCreate this container? Yes/No prompt.

Example: Wizard with Profile (Fast Path)

? Start from a profile?
  > sdr-full — Full SDR suite with all tools and device support

? Use profile 'sdr-full' as-is?
  > Yes, use as-is

? Container name: my_sdr_work

──────────────────────────────────────────────────
Container Configuration (from profile):
  Image:    penthertz/rfswift_noble:sdr_full
  Name:     my_sdr_work
  Network:  host
  Realtime: enabled
──────────────────────────────────────────────────

? Create this container? Yes

Example: Wizard without Profile

? Start from a profile?
  > No profile (manual configuration)

? Select an image:
  > penthertz/rfswift_noble: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_noble: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_noble: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
Non-interactive mode: The wizard only appears in interactive terminals. When piping or scripting, always provide -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/usb

High-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/captures

Repeatable 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/tcp

Remote 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 \
  --record

Isolated Analysis Container

rfswift run -i reversing -n isolated_analysis \
  -u 0 \
  -t none \
  -b ~/samples:/root/samples:ro \
  -b ~/output:/root/output \
  --no-x11

Troubleshooting

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_2

Image Not Found

Error: Error: No such image: penthertz/rfswift_noble: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 container

Device 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 cgroups add -c container -g "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_device

Network 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 bridge

X11 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-x11

Audio 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:34567

Port 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_name

Buffer 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_command

Best 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 test1

2. 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 capabilities add -c wifi_scan -a NET_ADMIN

3. Use Realtime Mode for SDR Work

# Always use --realtime for SDR captures
rfswift run -i sdr_full -n hackrf_capture --realtime

4. Use Read-Only Mounts for Reference Data

rfswift run -i analysis -n data_analysis \
  -b ~/samples:/root/samples:ro \
  -b ~/output:/root/output

5. Record Important Sessions

rfswift run -i pentest -n client_assessment \
  --record \
  --record-output client-$(date +%Y%m%d).cast

6. Use Bridge Network for Services

rfswift run -i web_tools -n web_server \
  -t bridge \
  -w 127.0.0.1:8080:80/tcp

7. 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.cast

Related Commands

  • profile - Manage container profiles (presets)
  • exec - Enter an existing container
  • stop - Stop a running container
  • remove - Remove a container
  • bindings - Dynamically add devices/volumes
  • capabilities - Modify capabilities after creation
  • cgroups - Modify cgroup rules after creation
  • ports - Manage ports after creation
  • realtime - Enable/disable realtime mode on existing containers
  • ulimits - Manage ulimits on existing containers
  • VPN Inside Containers - Detailed VPN setup guide
  • Using Podman - Podman-specific guidance

SDR Performance: Use --realtime flag for optimal SDR performance. It automatically configures rtprio, memlock, nice ulimits and SYS_NICE capability to eliminate buffer underruns!
💡
Tip: Use rfswift run --help to see all options with their current default values from your config file.
Last updated on