Skip to main content

RemoteRF server-side control package

Project description

Remote RF Server Guide (Linux)

Environment and setup

This guide installs Miniconda, installs mamba, creates a conda env named remoterf, installs dependencies, and verifies the install on Ubuntu Server 24.04 LTS.

  • This guide is done APT-based distro (Ubuntu/Debian/Raspberry Pi OS 64-bit).

1) System Prerequisites

sudo apt update
sudo apt install -y curl ca-certificates bzip2 git build-essential
sudo apt install -y libusb-1.0-0 udev

Optional: confirm architecture:

uname -m
  • x86_64 → Intel/AMD
  • aarch64 → ARM64 (Raspberry Pi 64-bit, some servers)

2) Install Miniconda

2.1 Download the installer

x86_64

cd /tmp
curl -fsSLO https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

ARM64 (aarch64)

cd /tmp
curl -fsSLO https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh

2.2 Install (non-interactive, recommended)

x86_64

bash Miniconda3-latest-Linux-x86_64.sh -b -p "$HOME/miniconda3"

ARM64 (aarch64)

bash Miniconda3-latest-Linux-aarch64.sh -b -p "$HOME/miniconda3"

2.3 Enable conda in your current shell

source "$HOME/miniconda3/etc/profile.d/conda.sh"
conda --version

If you want conda available automatically in new terminals:

"$HOME/miniconda3/bin/conda" init bash
source ~/.bashrc

2.4 Install mamba (default solver)

conda install -n base -c conda-forge -y mamba
mamba --version

Might have to accept anaconda TOS.

conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main

conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r

3) Create the Environment

mamba create -n remoterf -y -c conda-forge -c defaults  python=3.10 pip setuptools wheel grpcio protobuf python-dotenv numpy scipy libiio pylibiio libusb

conda activate remoterf
python -m pip install -U pip
python -m pip install pyadi-iio remoterf-server

Server Config

Depending on your IT/ISP setup, this will vary, but regardless, you will need a static dial name, whether that be a IP address or a DNS.

Generate CA Certificates

If direct IP connection: (force overrides existing)

serverrf --gen-certs 192.168.1.50 --days 3650 --force

If using DNS: (todo: DNS on client side)

serverrf --gen-certs 192.168.1.50 --dns remoterf.local --days 3650 --force

Confirm/View:

serverrf --show-certs

Specify Outward facing Ports

By default, the users expect to adjacent ports. Thus, it is recommended to do the following:

# examples
serverrf --config --main-port 61000 --cert-port 61001
serverrf --config --main-port 20000 --cert-port 20001
serverrf --config --main-port 32000 --cert-port 32001

Confirm/View:

serverrf --config --show

Testing Connection

The server now should be functional in its most basic form. In the same conda env:

serverrf --serve

If you see something along the lines of: self.socket.bind(self.server_address) PermissionError: [Errno 13] Permission Denied, make sure the ports you are using are not OS reserved (<1024)

Confirm it works locally

Start the server:

serverrf -s

For a loopback-only development server, explicitly bind both services to localhost:

REMOTERF_BIND_HOST=127.0.0.1 GRPC_PORT=55051 CERT_PORT=55052 \
  serverrf --serve --headless

Headless and interactive shutdown both stop accepting RPCs, close all Dynamic v2 sessions/handles and native devices, stop the certificate provider, and terminate the reservation-update worker.

Take note of the Local IP and Local Port, for example, if you see:

Local IP: 164.67.195.210
Local Port: 61000

then run the below on a seperate terminal (make sure to keep serverrf -s RUNNING!)

Confirm that its reachable:

nc -vz 164.67.195.210 61000
nc -vz 164.67.195.210 61001

Network Testing

Same test, but on a different computer. Works for UNIX based machines:

Confirm that the Server is reachable:

nc -vz 164.67.195.210 61000
nc -vz 164.67.195.210 61001

You most likely will need to port forward, etc.

Troubleshooting: Some distros come with default firewall settings that block traffic on specific ports. Make sure that your firewall settings permit traffic to and from the server. Depending on the setup, you may also have ISP firewalls.

Server Device Configuration

ADALM-Pluto and local UHD B200-family inventories are supported. USRP devices remain registered as device type usrp; runtime capabilities distinguish usrp2901 and b200.

To connect plutos to the server:

iio_info -s

If the pluto doesn't show up, yet the below works:

sudo iio_info -s

Run the below and reboot after:

sudo groupadd -f plugdev
sudo usermod -aG plugdev "$USER"

sudo tee /etc/udev/rules.d/53-adi-usb.rules >/dev/null <<'EOF'
# Type the below in
SUBSYSTEM=="usb", ATTR{idVendor}=="0456", MODE="0660", GROUP="plugdev"
EOF

sudo udevadm control --reload-rules
sudo udevadm trigger
sudo reboot now

The below should work as intended now:

iio_info -s

Look for 'serial='. Take note of this serial.

serverrf --device --add --pluto <device_id:name:serial>

# example
serverrf --device --add --pluto 0:pluto_0:104473f6
serverrf --device --add --pluto "1:Pluto SDR (OTA):58472j"

Run the below to check if this new device exists:

serverrf --device --show

Run the below to edit names of existing devices:

serverrf -d --edit-name 0 "New Name"

Note that all device and server config parameters need a 'restart' to take affect (ctrl + c -> serverrf -s).

NI USRP-2901 / B200-family

The server automatically installs and registers its complete USRP v1/v2 schema on first startup, so clients can discover the API even when UHD is not installed locally. Existing custom usrp drivers in ~/.config/remoterf/drivers/ take precedence over that default.

Opening a real USRP session requires the machine that owns the hardware to have the exact supported UHD Python API, UHD 4.10.0.0, installed. The server does not open the device while loading inventory. It opens the reservation's exact type=b200,serial=... device only when the authenticated client opens a v2 session.

Add a serial-bound device:

serverrf --device --add --usrp 7:usrp2901_lab:31A2B3C
serverrf --device --show

The canonical inventory is ~/.config/remoterf/devices.yml:

devices:
  - device_id: 7
    device_type: usrp
    name: usrp2901_lab
    init:
      serial: 31A2B3C

Transmit is denied if ~/.config/remoterf/usrp_policy.yml is missing, unreadable, invalid, or does not explicitly enable and bound the requested operation. Low-level writes are also denied unless both globally enabled and method/path/address allowlisted. A starting policy looks like:

defaults:
  tx_enabled: false
  low_level_write_enabled: false

devices:
  "31A2B3C":
    tx_enabled: true
    tx_frequency_ranges_hz:
      - [902000000, 928000000]
    max_tx_gain_db: 20
    max_tx_normalized_gain: 0.5
    max_tx_power_dbm: -10
    max_tx_bandwidth_hz: 2000000
    max_tx_sample_rate_sps: 2000000
    allowed_tx_antennas: [TX/RX]
    max_burst_seconds: 1.0
    max_duty_cycle: 0.1
    duty_cycle_window_seconds: 60
    low_level_write_enabled: false
    low_level_write_methods: []
    gpio_write_masks: {}
    property_write_paths: []
    register_write_addresses: []

On every qualified target, generate the introspection record and enforce the pinned API gate:

python -m remoteRF_server.tools.introspect_uhd \
  --output uhd-4.10.0.0-target.json

The command exits nonzero for a version mismatch, a missing required member, an unclassified public MultiUSRP member, or any still-deferred schema entry. Hardware differential, two-channel/full-duplex, USB 2/3, external clock/PPS, policy-bypass, and qualified-LAN performance tests remain mandatory release gates; they cannot be completed on a checkout without UHD and a physical NI USRP-2901.

To qualify the actual two-channel RX path through both checkouts on the Linux USRP host, run the opt-in localhost client/server test from the server repo:

REMOTERF_TEST_USRP_SERIAL=31A2B3C \
REMOTERF_CLIENT_SRC=../RemoteRF-Client/src \
python -m unittest discover -s tests \
  -p test_usrp_client_server_hardware.py -v

This opens the serial-bound device, negotiates the v2 schema over a real localhost gRPC socket, configures both RX channels through the client API, receives raw binary IQ, restores the prior RX settings, and closes the remote stream/session. It is RX-only and does not enable transmit.

Dynamic v2 control and SampleDataV1.SampleStream run on the existing TLS gRPC channel. IQ samples are carried as bounded raw binary payloads with dtype/shape/channel metadata; JSON/base64 and repeated-float sample transport are not used.

Server Runtime Configuration

After running serverrf --serve, you’ll enter the RemoteRF Server Shell. This interactive shell is used for runtime administration: users, devices, reservations, user groups, enrollment codes, and live host-tunnel state.


Server

  • help / h / ? — Show help
  • clear / cls — Clear the screen
  • status / server status — Show server status (start time / uptime / bind + cert ports)
  • quit / exit / q — Exit the server shell

Users

  • users list — List all accounts
  • users manage — Manage a specific user (perms / delete / reservations)
  • users purge — Delete all users
  • users perms — Show permissions table

Devices

  • devices list — List all devices
  • devices status — Show live device routing/online/last_seen from the Host Tunnel

Reservations

  • reservations list — List all reservations
  • reservations purge — Delete all reservations

Groups

  • groups list — List user groups
  • groups create — Create a user group (interactive)
  • groups edit — Edit a user group (interactive)
  • groups delete — Delete a user group (interactive)
  • groups csv — Export all groups as a CSV

Enrollment Codes

  • codes list — List enrollment codes
  • codes create — Create enrollment codes (interactive)
  • codes delete — Delete an enrollment code (interactive)
  • codes csv — Export all codes as a CSV

Host Tunnel

  • hosts status — Show live host online/last_seen and associated devices
  • hosts wipe — Wipe persisted host directory state and clear in-memory registry (prompts for confirmation)
  • hosts wipe -y / hosts wipe --yes — Same as above, no prompt

Database

  • db purge — Remove all database entries

Adding Hosts

You will need, for each host, to run this first on the server CLI:

serverrf --host --token-create host-name --length 8

Which will return the corresponding command to run on the respective host to give that host access to the server. Below are some other related commands (ie: 'whitelists' hosts)

serverrf --host --show
serverrf --host --delete host-name
serverrf --host --wipe

Status (Optional)

If you desire to pull the server information (ie: live updates of reservation, server usage parameters, etc.)

It uses GitHub Gists to push the status updates.

Create public gist on your github. Keep note of the file name: (example) https://gist.github.com/ethange1/2a35e08a90bf88a70dfe7f42a55685ed

The last one is the "GIST_ID" part of the URL, e.g. "2a35e08a90bf88a70dfe7f42a55685ed"

Creating the GitHub PAT Token

  • GitHub → Settings
  • Developer settings
  • Personal access tokens → Fine-grained tokens
  • Generate new token
  • Set repository access to "Public Respositories"
  • Permissions: enable Gists: Read and write
  • Generate + copy the token (you only see it once)
serverrf --gist --set --id <gist_id> --file <filename>

Run the server normally, and you should see your gist change every minute!

serverrf -s

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

remoterf_server-1.0.3.tar.gz (169.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

remoterf_server-1.0.3-py3-none-any.whl (161.2 kB view details)

Uploaded Python 3

File details

Details for the file remoterf_server-1.0.3.tar.gz.

File metadata

  • Download URL: remoterf_server-1.0.3.tar.gz
  • Upload date:
  • Size: 169.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for remoterf_server-1.0.3.tar.gz
Algorithm Hash digest
SHA256 cb495d5fcc7fafeaf38ca383ba5377d9f5f0eeeda7cbf2242c9e9022e7507876
MD5 da47457830495093980d2e677c5eb5e2
BLAKE2b-256 2dd7e350d72918a83ee173943e55ff2ea635a26d7039938b4d4ed05b23f61615

See more details on using hashes here.

File details

Details for the file remoterf_server-1.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for remoterf_server-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 4f2c5516b4e1e2ddd095f7d01ebcaa592890bc3ce0c7ac2b0a9b203b3cd89a65
MD5 c168fe087e6ce08704df872dd66911c8
BLAKE2b-256 ff21c61a65e8640092da5d9ac56bc48fffa42b735abb8df682b21c43e3598fb5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page