Orchestrator repository for Retina passive radar nodes. Manages docker-compose configuration and Mender OTA artifact generation.
Deploy to nodes running owl-os via the Mender dashboard. See owl-os README for installation instructions.
For development/testing without Mender, see STANDALONE.md.
Every node has a permanent address of its own, ret<node_id>.local, derived from
its Mender node_id and unchanged for the life of the board. The node's own page
shows it, under Configuration > This node.
| Service | Port | URL | Description |
|---|---|---|---|
| retina-gui | 80 | http://ret<node_id>.local |
Node management, SSH keys, service links |
| blah2 | 49152 | http://ret<node_id>.local:49152 |
Passive radar UI |
| tar1090 | 8078 | http://ret<node_id>.local:8078 |
ADS-B aircraft map |
| adsb2dd | 49155 | http://ret<node_id>.local:49155 |
Delay-Doppler truth overlay |
| retina-spectrum | 3020 | http://ret<node_id>.local:3020 |
Spectrum analyzer |
http://owl.local also reaches a node, but it is a shared name that every
node on the network answers, so with more than one node it reaches whichever
replies first. Use it to find a node; use ret<node_id>.local to work with a
particular one.
Add your SSH public key via the web GUI:
- On your computer, copy your public key:
cat ~/.ssh/id_ed25519.pub - Open
http://owl.localin a browser, and pick your node - Paste the key and click "Add Key"
- SSH in:
ssh node@ret<node_id>.local
Always SSH to the node's own ret<node_id>.local, never to owl.local. That
name is answered by every node on the network, so which host you reach can
change between connections and SSH will refuse on the host key mismatch.
Keys persist across reboots and OTA updates.
Check container status
sudo docker psView logs for a specific container
sudo docker logs <container-name>Restart / update config
cd /data/mender-docker-compose/current/manifests
sudo docker compose -p retina-node run --rm config-merger
sudo docker compose -p retina-node up -d --force-recreateAccess nodes via Mender troubleshooting terminal.
/data/
├── mender-docker-compose/current/manifests/
│ ├── docker-compose.yaml # Deployed compose file
│ └── .env # Environment vars (copied by config-merger and autogenerated)
│
└── retina-node/
├── config/
│ ├── user.yml # User config overrides (edit this)
│ ├── config.yml # Merged blah2 config (auto-generated)
└── blah2/
├── save/ # Persistent radar data
├── script/ # Runtime scripts
└── test/ # Test data
Config-merger generates config files at startup by merging:
default.yml → user.yml → forced.yml
Later files override earlier ones.
# 1. Edit config
sudo nano /data/retina-node/config/user.yml
# 2. Regenerate .env and restart services
cd /data/mender-docker-compose/current/manifests
sudo docker compose -p retina-node run --rm config-merger
sudo docker compose -p retina-node up -d --force-recreate
# 3. Verify
cat /data/retina-node/config/config.ymlAfter initial Mender deployment, run config-merger and restart to apply config:
cd /data/mender-docker-compose/current/manifests
sudo docker compose -p retina-node run --rm config-merger
sudo docker compose -p retina-node up -d --force-recreateWhy restart is needed: Docker Compose reads environment variables from .env at container start time, not when the file changes. Config-merger generates .env with location and ADS-B settings, but services that started before this file existed won't have the correct values. The restart ensures all services pick up the generated configuration. This is not needed if using the OWL-OS set-up wizard.
Edit files in config/ directory in this repo, then rebuild and deploy.
- Update
docker-compose.ymlwith desired package versions - Tag with
git tag vX.X.Xand push - CI workflow generates Mender artifact and uploads to dashboard