A live Reticulum network visualiser. Listens for announces on a Reticulum mesh network and displays nodes in real time on an interactive dartboard-style map, colour-coded by application type (LXMF, Nomadnet, Propagation, Audio).
Built for Ubuntu 22.04 with an RNode LoRa interface. The web UI is mobile-responsive and served locally — no internet connection required after installation.
RNode (LoRa hardware)
|
rnsd <-- systemd service, owns the RNode interface
|
rns_map.py <-- attaches as a shared-instance client (RNS.Reticulum())
| does NOT own any interfaces itself
|
aiohttp HTTP/WS server on port 8085
|
browser <-- static/index.html (SVG dartboard, live WebSocket feed)
rns-map is a client of rnsd — it never owns or starts its own RNS interfaces. rnsd must be running before rns-map starts. rns-map simply listens for announces that rnsd receives and forwards them to the web UI.
- Ubuntu 22.04 (other Debian-based distros likely work)
- Python 3.10+
- An RNode LoRa device (or any other Reticulum-supported interface)
rnsdrunning as a systemd service with at least one active interface- The installing user must have permission to write to
/etc/systemd/system/
Before following any steps below, answer this question:
Do you already have Reticulum (rnsd) installed and running on this machine,
for example as part of a MeshChat or Nomadnet setup?
- Yes → follow Scenario A
- No → follow Scenario B
This is the most common case. If you already run MeshChat, Nomadnet, or any other Reticulum application on this machine, rnsd is already handling your hardware interface. rns-map will attach to it automatically.
Do NOT set up a second rnsd. Do NOT copy config.example. Two rnsd instances trying to own the same hardware interface will conflict and both will fail.
1. Clone the repo:
git clone https://github.com/fotografm/rns-map.git ~/rns-map2. Run the install script:
bash ~/rns-map/install.sh3. Start the service:
sudo systemctl start rns-map
journalctl -u rns-map -fYou should see:
[rns-map] Loaded N nodes from DB
[rns-map] Announce handlers registered
[rns-map] Serving on http://0.0.0.0:8085
4. Open in browser:
http://<your-machine-ip>:8085
That's it. rns-map will start populating as announces arrive from your existing RNS network.
You need to set up rnsd first, then rns-map.
1. Clone the repo:
git clone https://github.com/fotografm/rns-map.git ~/rns-map2. Set up the Reticulum config:
cp ~/rns-map/reticulum-config/config.example ~/rns-map/reticulum-config/config
nano ~/rns-map/reticulum-config/configEdit the config to match your hardware. At minimum you need to set the correct
port for your RNode (check ls /dev/ttyUSB* or ls /dev/ttyACM*), and set
the correct frequency for your region. See the comments in config.example
for guidance.
3. Install Reticulum and create an rnsd systemd service.
Install the RNS package into rns-map's venv (install.sh will create it):
python3 -m venv ~/rns-map/venv
~/rns-map/venv/bin/pip install "rns==1.1.3"Create /etc/systemd/system/rnsd.service:
[Unit]
Description=Reticulum Network Stack Daemon
After=network.target
[Service]
Type=simple
User=user
ExecStart=/home/user/rns-map/venv/bin/rnsd --config /home/user/rns-map/reticulum-config
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Enable and start rnsd:
sudo systemctl daemon-reload
sudo systemctl enable rnsd
sudo systemctl start rnsd
journalctl -u rnsd -fWait until you see rnsd reporting it has initialised the interface before continuing.
4. Run the install script:
bash ~/rns-map/install.sh5. Start rns-map:
sudo systemctl start rns-map
journalctl -u rns-map -f6. Open in browser:
http://<your-machine-ip>:8085
The map loads but no nodes ever appear rnsd may not be receiving any announces yet — this is normal on a quiet network. LoRa announces can be infrequent. Leave the map open for 10–15 minutes. If you have Nomadnet or MeshChat running on the same machine they will generate announces immediately on startup.
rns-map starts but immediately crashes with a connection error
rnsd is not running or has not finished starting up. Check with
systemctl status rnsd. rns-map's systemd service has a 10-second restart
delay built in — it will retry automatically.
Port 8085 is already in use
Another service is using port 8085. Edit rns_map.py and change PORT = 8085
to a free port, then restart the service.
Permission denied on /dev/ttyUSB0
Your user is not in the dialout group. Fix with:
sudo usermod -aG dialout userThen log out and back in, or reboot.
Two rnsd instances clashing (Scenario A users who also ran config.example) If you accidentally started a second rnsd, stop and disable it:
sudo systemctl stop rnsd
sudo systemctl disable rnsdThen restart the original rnsd and rns-map.
The web UI shows a red dot and "reconnecting" in the status bar
The WebSocket connection to rns-map has dropped. This usually means rns-map
crashed or was restarted. Check journalctl -u rns-map -f. The browser will
reconnect automatically once the service is back up.
| Package | Version |
|---|---|
| rns | 1.1.3 |
| aiohttp | 3.9.5 |
| msgpack | 1.1.2 |
sudo systemctl status rns-map
sudo systemctl restart rns-map
sudo systemctl stop rns-map
journalctl -u rns-map -f| Method | Path | Description |
|---|---|---|
| GET | / |
Serves the web UI (index.html) |
| GET | /ws |
WebSocket — live announce events |
| GET | /activity |
JSON: per-minute announce counts |
| POST | /reset |
Wipe node database, reset the map |
All messages are JSON.
state — sent once on connect, full node list:
{"type": "state", "nodes": [...]}announce — new or updated node:
{"type": "announce", "node": {"hash": "...", "name": "...", "app_type": "lxmf", "hops": 2, "first_seen": 1234567890.0, "last_seen": 1234567890.0}, "ts": 1234567890.0}reset — node DB has been wiped:
{"type": "reset"}| Colour | Type | Aspect filter |
|---|---|---|
| Cyan | LXMF | lxmf.delivery |
| Green | Nomadnet | nomadnetwork.node |
| Orange | Propagation | lxmf.propagation |
| Purple | Audio | call.audio |
| Ring | Meaning |
|---|---|
| Centre | Direct (0 hops) |
| Ring 1 | 1 hop |
| Ring 2 | 2 hops |
| Ring 3 | 3+ hops |
MIT