Add svxdr: the live-data backend (nodelist + proxy; astmeta/xlink optional), config example, systemd unit, INSTALL section 9

svxdr sources from the internal repo with AGPL headers; install/svxdr.json.example is a plain-reflector
layout (reflector 8099 -> proxy 8090 -> nodelist 8098) with CHANGEME secrets and no site values.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 00:48:43 +02:00
co-authored by Claude Fable 5.1
parent 3322a9f625
commit 4e43e69583
18 changed files with 7763 additions and 21 deletions
+62 -14
View File
@@ -230,32 +230,80 @@ Answer the prompts (callsign, e-mail, password, admin level). Levels:
Log in on the web page with that callsign. The **Admin** menu appears.
## 9. Live data API — what this repository does NOT contain
## 9. Live data backend: svxdr
The dashboard (node list, map, monitor, last-heard, trunks) fetches JSON and
Server-Sent Events from `/svxportal/api/...`, which nginx proxies to
`127.0.0.1:8098`. That backend service is **not included** here. Without it
the account/admin/talkgroup pages work, but the front page's node list, map,
monitor, last-heard and trunks views simply stay **empty**. There is no error
banner: the API helper returns null on a failed fetch and the page keeps its
empty tables. Check the browser console (404 on `/svxportal/api/status`) if
you are unsure.
`127.0.0.1:8098`. That backend is **svxdr**, included in `svxdr/`: one Go
binary with four modules switched on or off per box in `/etc/svxlink/svxdr.json`.
Endpoints the UI expects:
| Module | What it does | A plain reflector needs it? |
|--------|--------------|-----------------------------|
| `proxy` | reads the reflector's own `/status`, caches it, serves it enriched on 8090 | yes |
| `nodelist` | builds the node/lastheard/monitor/trunk data from the proxy + Redis, serves `/api/*` on 8098 | yes |
| `astmeta` | AllStar/Asterisk AMI talker metadata for USRP bridges | no, leave `false` |
| `xlink` | relays talker events to an MQTT broker | no, leave `false` |
Without svxdr the account/admin/talkgroup pages work, but the front page's
live views stay **empty** with no error banner (404 on `/svxportal/api/status`
in the browser console).
### Build
```bash
sudo apt install golang-go # Go 1.24 or newer
cd svxdr && CGO_ENABLED=0 go build -trimpath -o svxdr . && cd ..
sudo install -m0755 svxdr/svxdr /usr/local/bin/svxdr
```
### Configure
```bash
sudo cp install/svxdr.json.example /etc/svxlink/svxdr.json
sudo chmod 640 /etc/svxlink/svxdr.json
sudoedit /etc/svxlink/svxdr.json
```
Set at least:
- `redis.socket` and `redis.password` -> the same Redis as `auth/config.php` (step 3).
- `proxy.reflector_status_url` -> your reflector's `HTTP_SRV_PORT` status URL.
With `HTTP_SRV_PORT=8099` in `svxreflector.conf` (as in
`install/svxreflector.conf.example`) the default `http://127.0.0.1:8099/status` is right.
- `nodelist.reflector_status_url` stays on the proxy (`http://127.0.0.1:8090/status`).
- All `CHANGEME` tokens: any random string; the ingest tokens only matter if a
remote box posts talker metadata to you.
- `nodelist.federation.seeds`: `/status` URLs of other reflectors you want in the
map that your own trunks do not reach. Empty = only what the crawl finds.
`aggregate_url` empty disables the gap detector.
The port layout must match the nginx config: reflector 8099 -> proxy 8090 ->
nodelist 8098 -> nginx `/svxportal/api/`.
### Run
```bash
sudo cp install/systemd/svxdr.service /etc/systemd/system/svxdr.service
sudo systemctl daemon-reload
sudo systemctl enable --now svxdr
systemctl status svxdr --no-pager
curl -s http://127.0.0.1:8098/healthz # -> ok
curl -s http://127.0.0.1:8098/api/status | head -c 300
```
Config changes are picked up with `sudo systemctl reload svxdr` (SIGHUP), no
restart needed. `journalctl -u svxdr -f` shows what it polls and serves.
Endpoints the UI uses:
| Path | Used by |
|------|---------|
| `/svxportal/api/status` | node table, topology |
| `/svxportal/api/status` | node table, topology, CTCSS |
| `/svxportal/api/stream` | live updates (SSE) |
| `/svxportal/api/lastheard` | last-heard list |
| `/svxportal/api/monitor-nodes` | monitor view |
| `/svxportal/api/local-trunks` | trunks view |
You need to provide something that serves these, for example a small service
that reads your reflector's `HTTP_SRV_PORT` status endpoint
([GeuReflector](https://github.com/audric/GeuReflector) serves `/status` there)
and republishes it. The static reflector status page in `help.html` describes the fields.
## 10. Reflector admin features (optional, need sudo helpers)
The pages **Admin → Reflector**, **Certificates**, **Node control** and **MQTT**