Self-hosted relay — deployment guide
The self-hosted relay is a standalone binary that extends Muster's mesh across networks without the traffic transiting Safe Signals' cloud relay. Deploy it when your department:
- Has data-residency requirements that keep mesh traffic on-premises.
- Wants federation resilience against internet outages at the firehouse.
- Runs a multi-station deployment and wants each station's local mesh to survive a WAN failure.
- Has strict cybersecurity policies that disallow cloud data flow.
Tier requirement: Tier 2 and above. Emergency and Tier 1 don't include self-hosted relay licensing.
Full technical reference: contact
support@safesignals.io to request the self-hosted relay
architecture and deployment specification.
Table of contents
- What the relay does
- Hardware and platform choices
- Install on Linux
- Install on Windows
- Install via Docker
- Provision the relay in the admin console
- Point devices at the relay
- Operations
- Troubleshooting
What the relay does
The relay is a Dart daemon that:
- Accepts device registrations on port 8443 via WebSocket.
- Verifies each device's License Key against the shared Muster issuer public key.
- Pairs devices into tunnels so they can exchange end-to-end-encrypted mesh events even when they can't discover each other via mDNS on the local network.
- Federates upstream to the Safe Signals cloud relay so devices behind the self-hosted relay can still participate in mutual-aid scenarios with departments that don't have their own relay.
The relay is not a general-purpose mesh transport. It handles WebSocket + JSON envelopes; the payloads are ChaCha20-Poly1305 AEAD-encrypted bytes the mobile app sends and receives. The relay never sees plaintext incident data.
Hardware and platform choices
Recommended:
- Raspberry Pi 4 (2 GB RAM or higher) — cheapest option that handles 25-50 devices with headroom. ~$50 for the hardware.
- Existing Linux server if your department already runs
one (
systemdunit ships with the relay). - Docker container if you have a container platform.
- Windows Server or Windows 10/11 machine with the Inno Setup installer if your department is Windows-shop.
Not recommended:
- Consumer routers with custom firmware — the resource profile is too tight for the WebSocket registrations.
- Anything without a stable IP address on the department LAN.
- Public cloud VMs (defeats the "self-hosted" purpose; Safe Signals' Stage 1 cloud relay is the correct choice if you want cloud hosting).
Install on Linux
-
Download the tarball from
https://releases.safesignals.io/relay/linux/muster-relay-<version>.tar.gz. -
Extract:
sudo tar -xzf muster-relay-<version>.tar.gz -C /opt/ -
Run the install script:
sudo /opt/muster-relay/install.shThe script:
- Creates a
muster-relaysystem user. - Copies the binary to
/usr/local/bin/muster_relay. - Installs the systemd unit to
/etc/systemd/system/muster-relay.service. - Generates the Ed25519 identity key at
/etc/muster-relay/identity.ed25519. - Drops a sample config at
/etc/muster-relay/config.yamlthat you'll edit next.
- Creates a
-
Edit
/etc/muster-relay/config.yaml. The YAML shape:identity: private_key_file: /etc/muster-relay/identity.ed25519 license: scope_token_file: /etc/muster-relay/scope.token network: listen_address: 0.0.0.0 # bind all interfaces listen_port: 8443 # tls: # cert_file: /etc/muster-relay/tls.crt # key_file: /etc/muster-relay/tls.key federation: upstream: endpoint: wss://relay.safesignals.io auth_token_file: /etc/muster-relay/federation.token ops: status_listen_addr: 127.0.0.1:9090 # loopback-only log_level: infoThe
scope.tokenandfederation.tokenfiles are the department-admin-signed tokens you'll download from the admin console in the next section. See config.example.yaml in the repo for the full annotated example. -
Start the daemon:
sudo systemctl enable --now muster-relay sudo systemctl status muster-relay -
Verify the daemon is up:
curl http://127.0.0.1:9090/statusThe response is a JSON document with the daemon's version, uptime, registered device count, and federation link state.
Install on Windows
-
Download the installer from
https://releases.safesignals.io/relay/windows/Muster-Relay-Setup-<version>.exe. -
Run the installer. It:
- Places the binary at
C:\Program Files\Muster Relay\muster_relay.exe. - Registers a Windows service via
sc.exe create. - Generates the Ed25519 identity key at
C:\ProgramData\Muster Relay\identity.ed25519. - Drops a sample config at
C:\ProgramData\Muster Relay\config.yaml.
- Places the binary at
-
Edit the config (same schema as the Linux example above).
-
Start the service:
sc.exe start "Muster Relay" -
Verify at
http://127.0.0.1:9090/status.
Firewall: the installer adds a Windows Defender Firewall rule for TCP 8443 inbound. If your department uses Group Policy to manage firewall rules, mirror the rule there.
Install via Docker
-
Pull the image:
docker pull gcr.io/muster-services/muster-relay:<version> -
Prepare a host directory for the persistent config and identity:
mkdir -p /srv/muster-relay docker run --rm -v /srv/muster-relay:/etc/muster-relay \ gcr.io/muster-services/muster-relay:<version> genkey -
Drop your config at
/srv/muster-relay/config.yaml(same schema as Linux above). -
Run:
docker run -d --name muster-relay \ -p 8443:8443 \ -p 9090:9090 \ -v /srv/muster-relay:/etc/muster-relay \ --restart unless-stopped \ gcr.io/muster-services/muster-relay:<version> startOr use the
docker-compose.ymlsample bundled atapps/relay_daemon/packaging/docker/docker-compose.ymlin the project repository. -
Verify:
curl http://<host>:9090/status.
Provision the relay in the admin console
Before the relay can federate upstream, the department's chief must provision it. In the admin console:
-
Go to Devices.
-
Click → Provision a self-hosted relay (chief / admin only). This lands on the Provision Relay page.
-
On the relay host, read the relay's Ed25519 fingerprint from the
/statusendpoint (which the daemon binds to127.0.0.1:9090by default per section §"Operations"):curl -s http://127.0.0.1:9090/status | jq -r .identity_fingerprint(Docker:
docker exec muster-relay curl -s http://127.0.0.1:9090/status | jq -r .identity_fingerprint.) -
Paste the fingerprint into the admin console form.
-
Click Generate provisioning tokens. The console downloads two files:
scope.token— authorizes the relay's device scope (department id + mode).federation.token— authorizes federation to the upstream cloud relay.
-
Copy both files to the relay host at
/etc/muster-relay/(Linux) orC:\ProgramData\Muster Relay\(Windows) or/srv/muster-relay/(Docker host mount). -
Restart the daemon so it picks up the new tokens.
Point devices at the relay
Two options for pointing Muster devices at the self-hosted relay:
Per-device override (small deployments): each device's
operator opens Settings → Peer Mesh → Cloud relay → Custom
endpoint and enters the relay's wss:// URL (e.g.,
wss://relay.station-1.fd-example.local:8443).
Department-wide default (recommended for departments with an MDM): the admin console's Devices → Relays → Push relay URL to all devices action stamps every activated device's License Key with the department's relay URL. New devices activated after that inherit the URL automatically.
Operations
Status endpoint (/status) returns:
{
"version": "0.1.0",
"uptime_seconds": 12345,
"identity_fingerprint": "…",
"registered_devices": 12,
"federation": {
"upstream_url": "wss://relay.safesignals.io/…",
"state": "connected",
"last_reconnect_at": null
}
}
Health endpoint (/health) returns 200 OK if the daemon
is running and the identity key is loadable. Use this as a
container HEALTHCHECK or an external monitor probe.
Logs:
- Linux:
journalctl -u muster-relay -f. - Windows: Event Viewer → Applications and Services Logs → Muster Relay.
- Docker:
docker logs -f muster-relay.
Upgrading:
- Download the new package version.
- Stop the daemon.
- Replace the binary (Linux/Docker) or run the installer (Windows).
- Start the daemon.
- Verify at
/statusthat the version reported matches the new release.
Configs, identity keys, and provisioning tokens are preserved across upgrades.
Troubleshooting
Daemon won't start
muster_relay validate-config /etc/muster-relay/config.yamlreports any YAML parse or field-validation errors without starting the daemon. Run it first.- Systemd exit codes surface in
journalctl -u muster-relay.
Devices can't connect
- Verify TCP 8443 is reachable from the device's network
(test with
curl -v https://<relay-host>:8443/health). - Verify the device's Muster tier is Tier 2 or above.
- Check the daemon logs for
LicenseAuthException— the device's License Key may be expired, revoked, or issued against a different issuer key.
Federation upstream shows disconnected
- Verify outbound TCP 443 to
relay.safesignals.iofrom the relay host. - Verify the
federation.tokenfile matches the fingerprint the admin console generated for. If you regenerated the identity key, the token is invalid and you must re-provision.
Identity key lost
- Re-run
muster_relay genkeyto create a new one. - Re-provision in the admin console (Devices → Relays → Re-provision existing relay). The old provisioning tokens become invalid; every device that had the old relay's URL cached needs its next mesh session to re-negotiate.
For deeper diagnostics, capture a status snapshot + recent
logs and email support@safesignals.io with your
department id.