Files
homelab/netbird

NetBird

Self-hosted NetBird with the combined management, signal, relay, and STUN server.

Kubernetes runs the server and dashboard in netbird. The server uses SQLite in netbird-pvc; k8s/config.yaml contains the template and runtime renderer. Prepare netbird-secrets from k8s/secrets.yaml.example before the first start.

Routing and keys

The public hostname is set in the ConfigMap and ingress rules. Keep the issuer, dashboard endpoints, and public routes consistent. HTTP, WebSocket, and gRPC traffic go through Traefik; the STUN route uses UDP 3478. A CDN's HTTP proxy does not provide that UDP listener.

NETBIRD_PROXY_SUBNET controls which forwarded client addresses are trusted. Use the actual proxy network CIDR rather than assuming another lab's subnet. Keep the datastore encryption key with every datastore backup. Regenerating it can make stored credentials unreadable.

Compose alternative

compose.yaml expects entrypoint.sh, a local .env, and two local files: secrets/relay-auth-secret and secrets/datastore-encryption-key. The reviewed main commit is missing the renderer and setup script. fix/netbird-compose-runtime restores them. Merge that fix before following these setup commands:

cd netbird
./setup.sh
$EDITOR .env
docker compose config --quiet
docker compose up -d

The setup script detects the IPv4 subnet of the external proxy network and preserves existing secrets. Complete the initial owner setup through the public TLS endpoint after starting the server.

Optional host client

client.compose.yaml runs a host-network peer in a separate Compose project. Set NB_SETUP_KEY and NETBIRD_CLIENT_HOSTNAME in the local .env, then run docker compose -f client.compose.yaml up -d. It needs /dev/net/tun and elevated network capabilities. The normal server deployment does not start this client.

Backup

Back up the SQLite data while the server is stopped, together with the encryption key, relay secret, and local configuration. Test a restore on an isolated host. For Compose, the datastore volume has the explicit name netbird_data. Do not use docker compose down -v when keeping the installation.

Inspect

From the repository root:

kubectl get pods,svc,pvc -n netbird
kubectl get events -n netbird --sort-by=.metadata.creationTimestamp

See the repository README for deployment selection.