A self-hosted, read-only dashboard for monitoring compatible Trunk Recorder Pro nodes, radio activity, recorder health, and optional Broadcastify listener statistics.
  • JavaScript 42.3%
  • CSS 29.9%
  • TypeScript 27.4%
  • Dockerfile 0.3%
  • HTML 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-19 17:43:21 -04:00
docs Show live emergency overlays and retain independent event history 2026-10-16 21:31:54 -04:00
scripts Public v2.0.0 release 2026-10-16 11:57:41 -04:00
server Ignore Icecast queue warnings in node health 2026-10-19 17:43:21 -04:00
src Refine Overview emergency activity and Eastern daily totals 2026-10-17 22:34:57 -04:00
tests Ignore Icecast queue warnings in node health 2026-10-19 17:43:21 -04:00
.dockerignore Public v2.0.0 release 2026-10-16 11:57:41 -04:00
.gitignore Public v2.0.0 release 2026-10-16 11:57:41 -04:00
CHANGELOG.md docs: publish v2.0.1 beta guidance 2026-10-16 12:21:33 -04:00
compose.broadcastify.yaml Public v2.0.0 release 2026-10-16 11:57:41 -04:00
compose.yaml Public v2.0.0 release 2026-10-16 11:57:41 -04:00
config.example.json Public v2.0.0 release 2026-10-16 11:57:41 -04:00
CONTRIBUTING.md Public v2.0.0 release 2026-10-16 11:57:41 -04:00
Dockerfile Public v2.0.0 release 2026-10-16 11:57:41 -04:00
index.html Public v2.0.0 release 2026-10-16 11:57:41 -04:00
LICENSE Public v2.0.0 release 2026-10-16 11:57:41 -04:00
NOTICE Public v2.0.0 release 2026-10-16 11:57:41 -04:00
ossscanner-verify.txt Add ossscanner-verify.txt 2026-10-16 13:57:58 -04:00
package-lock.json fix: reject malformed radio replies 2026-10-16 13:59:34 -04:00
package.json fix: reject malformed radio replies 2026-10-16 13:59:34 -04:00
README.md Show live emergency overlays and retain independent event history 2026-10-16 21:31:54 -04:00
SECURITY.md docs: publish v2.0.1 beta guidance 2026-10-16 12:21:33 -04:00
tsconfig.json Public v2.0.0 release 2026-10-16 11:57:41 -04:00

Trunk Fleet Monitor

Public beta — v2.0.3

Release License

A self-hosted, read-only dashboard for compatible Trunk Recorder Pro nodes, radio activity, recorder health, and optional Broadcastify listener statistics.

The Overview page shows fleet health and current Broadcastify listener counts. The Listeners page provides five-minute history, averages, peaks, and charts. The monitor never plays, proxies, stores, or archives audio and cannot start, stop, or configure recorders.

Screenshots

Fleet overview

Broadcastify listener history

Quick start

Requires Docker Engine with the Compose plugin and network access from the container to a compatible recorder.

cp config.example.json config.json
# Edit config.json with a reachable recorder URL.
docker compose up -d --build

Open http://localhost:8081. The example hostname is deliberately nonfunctional. Inside Docker, localhost means the monitor container. Set APP_PORT to change the published host port.

The Setup page in the dashboard provides configuration and access guidance. Configuration remains file-based: the browser does not write server settings. Keep actual settings in the ignored config.json and commit only fictional examples.

Configure nodes and Broadcastify

A node is a recorder instance. Add a stable ID, display name, and HTTP/HTTPS origin to config.json. Up to 16 enabled nodes are supported. Systems, channels, talkgroups, SDR assignments, and plugins remain configured in the recorder and are discovered by the monitor.

Broadcastify is optional. Enable it in the settings, add feed IDs and labels, and provide credentials through Docker secrets or host-only secret files. Listener history is stored in the data volume for 30 days. Never commit credentials, private recorder URLs, caches, logs, or deployment files.

See configuration, recorder setup, deployment, and troubleshooting.

Compatibility, privacy, and limits

This release consumes the Trunk Recorder Pro JSON WebSocket protocol at /api/ws. Radio analytics additionally require read-only radioQuery and call-outcome statsQuery capabilities. Other recorder distributions and unsupported Pro versions are not guaranteed to work; report the recorder version when opening an issue.

The viewer has no built-in login. Protect it with a reverse proxy, VPN, firewall, or private network before sharing it. Apply the same access control to HTML, API, and WebSocket routes. Upstream recorder authentication is not implemented.

Recorder history is bounded in memory. Missing observations remain unknown rather than zero. The service is intentionally read-only and has no audio archive.

Release and development

The version below the title comes from package.json; the build ID is generated from application source. Run npm ci, npm test, and npm run build. Browser checks use Playwright separately. The public release tag is v2.0.3-public; the previous v2.0.0 image and private deployment snapshot are rollback points.

See changelog, roadmap, security reporting, and contributing.

License

GPL-3.0-or-later. See LICENSE and NOTICE.

Emergency button alerts

Fleet Monitor subscribes to both platform and emergency on each recorder's /api/ws. Recorders must include the browser bridge that emits Output::Topic { topic: "emergency", ... }; Discord/plugin delivery alone does not supply these browser events. See docs/emergencies.md for the wire format and verification steps.

New emergency events show a full-screen red Emergency Button alert on any dashboard page. It shows the node, system, talkgroup, radio, source and timestamp. Dismiss it immediately or let it close after ten seconds. Each new event replaces the current overlay and restarts its timer. Reduced-motion settings disable the pulse. Existing history is not replayed as new alerts when opening or reconnecting the dashboard.

The compact Overview history and Emergencies tab retain up to 200 independent events per node, with node/system filters. Repeated events with identical fields remain distinct. History survives overlay dismissal and recorder reconnections, but is held in monitor memory and clears when the monitor process restarts. No audio or recorder commands are introduced.