boma/roles/netbird_coordinator
sjat ab1b0678ab feat(netbird): coordinator service role (combined server + dashboard, v0.72.4)
First real service role. NetBird v0.72.4 self-hosted control plane: single
netbirdio/netbird-server:0.72.4 (management + signal + relay + STUN + embedded
Dex) plus netbirdio/dashboard:v2.39.0, both on the shared boma Docker network so
the M4a Caddy fronts them. Renders docker-compose.yml + config.yaml (secrets from
vault.netbird.*, no_log) + dashboard.env. STUN 3478/udp host-exposed; everything
else via the proxy. netbird_coordinator__manage gates the compose-up for Molecule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:49:57 +02:00
..
defaults feat(netbird): coordinator service role (combined server + dashboard, v0.72.4) 2026-06-15 17:49:57 +02:00
handlers feat(netbird): coordinator service role (combined server + dashboard, v0.72.4) 2026-06-15 17:49:57 +02:00
meta feat(netbird): coordinator service role (combined server + dashboard, v0.72.4) 2026-06-15 17:49:57 +02:00
molecule/default feat(netbird): coordinator service role (combined server + dashboard, v0.72.4) 2026-06-15 17:49:57 +02:00
tasks feat(netbird): coordinator service role (combined server + dashboard, v0.72.4) 2026-06-15 17:49:57 +02:00
templates feat(netbird): coordinator service role (combined server + dashboard, v0.72.4) 2026-06-15 17:49:57 +02:00
README.md feat(netbird): coordinator service role (combined server + dashboard, v0.72.4) 2026-06-15 17:49:57 +02:00

netbird_coordinator

Self-hosted NetBird coordinator — the mesh-VPN control plane (ADR-016). Runs on askari (the off-site Hetzner host) and is the rendezvous point every NetBird peer talks to. Deployed via Docker Compose (ADR-004), behind the Caddy reverse proxy.

Architecture — combined server

NetBird's self-hosted stack is now a single combined server image plus a separate dashboard UI — there is no longer a separate signal / relay / coturn / dex container, and no turnserver.conf / management.json / openid-configuration.json.

Container Image Role
netbird-server netbirdio/netbird-server Management API + Signal + Relay + STUN + embedded Dex IdP (/oauth2), all on one process. Config at /etc/netbird/config.yaml. State in the netbird_data volume (SQLite).
netbird-dashboard netbirdio/dashboard Web UI. Configured purely by environment (dashboard.env); a public PKCE OIDC client, so its client secret is intentionally empty.

Both containers join the existing external boma Docker network (created by the reverse_proxy role's compose) so Caddy reaches them by container name. The only host-exposed port is 3478/udp (STUN); HTTP/gRPC/WS traffic enters via Caddy over the boma network, not via host ports.

Reverse-proxy routing (added separately — M4a Caddy)

This role does not add the Caddy route. The route is a separate task and must front several upstreams on netbird-server over the boma network, all to the same backend:

  • HTTP — /api/*, /oauth2/*
  • Native gRPC (h2c) — /signalexchange.SignalExchange/*, /management.ManagementService/*
  • WebSocket — /relay*, /ws-proxy/* (upgrade + long timeouts)
  • Dashboard catch-all — /*netbird-dashboard

gRPC needs HTTP/2 (h2c) upstream support; WS/gRPC need extended timeouts.

Variables — netbird_coordinator__*

Variable Default Description
netbird_coordinator__server_image netbirdio/netbird-server:0.72.4 Combined server image (pinned; never latest)
netbird_coordinator__dashboard_image netbirdio/dashboard:v2.39.0 Dashboard image (versioned independently of the server)
netbird_coordinator__base_dir /opt/services/netbird Working directory for the Compose project
netbird_coordinator__domain netbird.askari.wingu.me Public hostname; feeds exposedAddress, the OIDC issuer, redirect URIs, and the dashboard endpoints
netbird_coordinator__trusted_proxies ["172.16.0.0/12"] Source ranges NetBird trusts X-Forwarded-* from (server.reverseProxy.trustedHTTPProxies). Must cover Caddy's source IP on the boma network — verify the actual bridge subnet at deploy
netbird_coordinator__manage true Set false in Molecule to render templates without a Docker daemon

Production overrides live in inventories/production/group_vars/.

Secrets

Two secrets come from the vault and are rendered into the host-side config.yaml (mode 0640, no_log); they never touch the work tree or the dashboard:

  • vault.netbird.auth_secretserver.authSecret
  • vault.netbird.datastore_keyserver.store.encryptionKey (base64; keep the padding)

The dashboard's OIDC client is a public PKCE client, so AUTH_CLIENT_SECRET is intentionally empty — dashboard.env carries no secrets.

netbird_coordinator__manage toggle

Docker operations (docker compose up, the restart handler) are gated on netbird_coordinator__manage | bool. Molecule sets it false so the role can be tested (template rendering, directory creation) without a Docker daemon.