Configuration and security
The sdrmm binary runs the receiver engine, REST API, WebSocket and MCP endpoints, Swagger UI,
and embedded React application in one process.
Command-line options
sdrmm [OPTIONS]
| Option | Default | Purpose |
|---|---|---|
--bind <ADDRESS> | 0.0.0.0:8080 | Address and port for HTTP and WebSocket traffic |
--db <PATH> | Platform data directory | SQLite database for workspaces, presets, bookmarks, recording index, and decoder log |
--recordings-dir <PATH> | Platform data directory | Directory containing SigMF recording pairs |
--token <TOKEN> | None | Require one shared bearer token for API, WebSocket, and MCP requests |
--routing-backend <NAME> | open-route-service | Routing service: open-route-service or graph-hopper |
--routing-url <URL> | The backend’s own service | Base URL, for a self-hosted instance |
--routing-key <KEY> | None | API key for that service |
--dev-cors | Off | Allow a separate frontend development origin |
--doctor | Off | Print environment diagnostics and exit |
--help | Show CLI help | |
--version | Show the build version |
Relative database and recording paths are resolved at startup. Use absolute paths for services and containers so storage does not depend on the working directory.
Persistent data
The SQLite database contains configuration and structured history. The recordings directory contains large IQ files. Back up both when you need a complete installation:
/srv/sdrmm/
├── sdrmm.db
└── recordings/
├── <capture>.sigmf-meta
└── <capture>.sigmf-data
Stop the server or use SQLite’s supported backup mechanism before copying a live database. Raw recording pairs can be copied while idle; do not assume an actively written pair is complete.
Logging
sdr– uses the standard RUST_LOG filter. Without an override it logs general information and
more detailed sdr– messages. Examples:
RUST_LOG=info sdrmm
RUST_LOG=sdrmm=trace,info sdrmm
Trace logging can be noisy on an active receiver. Capture it for a short diagnostic session rather than leaving it enabled on an unattended server.
Shared-token authentication
By default, a headless server is unauthenticated and trusts its local network. Set a long random token whenever untrusted clients can reach the port:
export SDRMM_TOKEN='replace-with-a-long-random-secret'
sdrmm
The environment variable avoids exposing the secret in the process list. --token and
SDRMM_TOKEN configure the same value.
The browser prompts for the token and stores it in local storage for that origin. REST and MCP clients should send:
Authorization: Bearer replace-with-a-long-random-secret
WebSocket handshakes and browser download links can use ?token=... because those requests cannot
always attach an authorization header.
The application shell and GET /api/auth remain reachable without authentication so the browser
can load and discover that it needs a token. Other API, WebSocket, documentation, and MCP routes
are protected.
Network security
The shared token is access control, not transport encryption. A plain HTTP client on the network can expose it and receiver traffic to an observer. For access beyond a trusted LAN:
- bind to loopback and place an HTTPS reverse proxy or authenticated tunnel in front;
- preserve WebSocket upgrade headers for
/api/ws; - proxy the application at the origin root rather than a path prefix;
- keep the direct
8080port firewalled; - rotate the shared token if it may have leaked.
sdr– has one shared privilege level. It does not currently provide per-user accounts or read-only roles, and every authenticated client can change the active receiver.
Turn-by-turn routing
Field mode can request driving routes to direction-finding waypoints.
The server proxies requests to OpenRouteService or GraphHopper and sends the API key in an
Authorization header. The key is not sent to the browser or included in URLs.
Set --routing-key for the hosted backend. Use --routing-backend to choose the service and
--routing-url for a self-hosted instance.
Without a configured or reachable backend, field mode reports that routing is unavailable and uses heading guidance. The phone’s navigation app remains available through Navigate in Maps.
Development CORS
--dev-cors installs a permissive CORS policy for the separate Vite origin used during frontend
development. It is not needed when the UI is served by sdrmm, and should not be enabled as a
production cross-origin access policy.