Lightweight headless deployment for KrakenSDR Direction of Arrival (DoA) estimation. Runs on Raspberry Pi 4 without the web UI, saving ~200MB RAM.
Runs the KrakenSDR DSP signal processing pipeline without Dash, Plotly, Node.js, PHP, or matplotlib. A built-in HTTP server on port 8081 serves DoA results and accepts settings updates from a remote app.
This repository contains only original code. The upstream KrakenRF repositories are cloned at install time — their code, their license, their ownership.
git clone https://github.com/Knobee/krakensdr-headless.git
cd krakensdr-headless
./install.sh
# Reboot, or start manually:
./start.sh# Build (on a Pi 4, takes ~40 min first time):
docker build -t krakensdr-headless .
# Run:
docker run -d \
--name krakensdr \
--privileged \
--network host \
--shm-size=256m \
--restart always \
-v krakensdr-data:/opt/krakensdr/krakensdr_doa/_share \
krakensdr-headlessPort 8081 serves the _share/ directory plus a synthetic status endpoint:
GET /settings.json— current configurationGET /DOA_value.html— real-time DoA results (CSV format)GET /status.json— DAQ hardware statusGET /headless_status.json— DoA health monitoring (see below)POST /settings.json— update configuration (full JSON body, read-modify-write)
Settings must be updated via a read-modify-write pattern:
GET /settings.jsonto read the current full settings- Modify the keys you need to change
POST /settings.jsonwith the complete JSON object
Do not POST partial settings — the entire object is replaced on disk.
Frequency and gain changes are applied to the DAQ hardware automatically (retune commands sent over the control interface).
GET /headless_status.json returns:
{
"doa_active": true,
"doa_age_seconds": 0.4,
"reason": "ok",
"daq_ok": true,
"frames": 4128
}| Field | Description |
|---|---|
doa_active |
Whether DoA data is currently being produced |
doa_age_seconds |
Seconds since DOA_value.html was last updated |
reason |
"ok", "no_signal_above_squelch", or "no_doa_data_yet" |
daq_ok |
Whether the DAQ hardware subsystem is healthy |
frames |
Number of DAQ frames processed since startup |
When doa_active is false and reason is "no_signal_above_squelch", the system is healthy but not hearing any signal strong enough at the tuned frequency. This is normal — not an error.
krakensdr-headless (this repo)
├── src/config/ shared constants, paths, settings loader
├── src/kraken_headless.py entry point (HTTP server + DSP)
└── src/patches/ minimal import patches for upstream
upstream (cloned at install time):
├── heimdall_daq_fw/ DAQ firmware (C, compiled for ARM)
└── krakensdr_doa/ DSP signal processing (Python)
Three lines are patched in upstream code at install time:
kraken_sdr_signal_processor.py—from variables import→from _config importkraken_sdr_receiver.py—from variables import→from _config importpyargus/directionEstimation.py— lazy-load matplotlib (only used for plotting, never called in headless mode)
All patches are idempotent and can be re-applied safely.
- Raspberry Pi 4 (4GB recommended) running Raspberry Pi OS (64-bit)
- KrakenSDR hardware connected via USB
- For Docker: Docker Engine (
curl -fsSL https://get.docker.com | sh)
This repository's original code is provided as-is. The upstream KrakenSDR software is licensed under its own terms — see the KrakenRF repositories.