NetBird
Deploy NetBird on Kubernetes as a self-hosted WireGuard overlay control plane for device management, identity-aware access, and peer coordination.
Overview
The HelmForge NetBird chart follows the current upstream combined self-hosted architecture:
netbirdio/netbird-server:0.74.4for the management API, gRPC endpoint, signal, relay, metrics, health, and UDP STUN servicenetbirdio/dashboard:v2.90.3for the web dashboard- Secret-backed
config.yaml, either generated from values or supplied throughserver.config.existingSecret - HelmForge PostgreSQL subchart as the default production store
- persistent server data under
/var/lib/netbird - separate server and dashboard Services
- Ingress and Gateway API HTTPRoute support
- UDP
3478Service exposure for STUN - External Secrets Operator, NetworkPolicy, PDB, dual-stack service fields, and Helm tests
Configuration Reference
Server:
server.image.repository,server.image.tag,server.image.pullPolicy: official pinned NetBird server image.server.replicaCount: server pod count. Keep1with the default sqlite store.server.publicUrl: externally reachable URL for dashboard, API, gRPC, signal, and relay traffic.server.authSecret: shared server auth secret. Replace the default before production use.server.disableAnonymousMetrics,server.disableGeoliteUpdate: upstream telemetry and GeoLite controls.server.config.existingSecret,server.config.existingSecretKey,server.config.extraYaml: generated or externally suppliedconfig.yaml.server.auth.issuer,server.auth.localAuthDisabled,server.auth.signKeyRefreshEnabled: embedded or external OIDC settings.server.auth.owner.email,server.auth.owner.password: optional local owner bootstrap.server.store.engine,server.store.dsn,server.store.encryptionKey: legacy direct sqlite, postgres, or mysql store settings.server.service.type,server.service.httpPort,server.service.stunPort,server.service.metricsPort,server.service.healthPort.server.probes.enabled: opt-in health probes for environments where first boot completes within the configured timeout.
Database:
database.mode:auto,sqlite,postgresql, orexternal.database.external.engine: externalpostgresormysql.database.external.host,database.external.port,database.external.name,database.external.username.database.external.password,database.external.existingSecret,database.external.existingSecretPasswordKey,database.external.dsn.postgresql.enabled,postgresql.auth,postgresql.standalone.persistence: bundled HelmForge PostgreSQL store.
Dashboard:
dashboard.enabled: deploy the dashboard UI.dashboard.image.repository,dashboard.image.tag,dashboard.image.pullPolicy: official pinned dashboard image.dashboard.replicaCount: dashboard pod count.dashboard.auth.clientId,dashboard.auth.audience,dashboard.auth.supportedScopes,dashboard.auth.tokenSource,dashboard.auth.useAuth0: dashboard OIDC environment.dashboard.securityContext: dashboard-specific runtime security context for upstream supervisord and nginx.dashboard.service.type,dashboard.service.port,dashboard.service.annotations,dashboard.service.ipFamilyPolicy,dashboard.service.ipFamilies.
Shared operations:
imagePullSecrets,commonLabels,nameOverride,fullnameOverride.persistence.enabled,persistence.size,persistence.storageClass,persistence.accessModes,persistence.existingClaim,persistence.mountPath.serviceAccount.create,serviceAccount.name,serviceAccount.annotations,serviceAccount.automountServiceAccountToken.ingress.enabled,ingress.ingressClassName,ingress.annotations,ingress.hosts,ingress.tls.gatewayAPI.enabled,gatewayAPI.httpRoutes.externalSecrets.enabled,externalSecrets.items.pdb.enabled,pdb.minAvailable.networkPolicy.enabled,networkPolicy.ingressFrom,networkPolicy.extraEgress.resources,podSecurityContext,securityContext,nodeSelector,tolerations,affinity.topologySpreadConstraints,priorityClassName,terminationGracePeriodSeconds.podLabels,podAnnotations,extraVolumes,extraVolumeMounts,extraManifests.
Installation
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install netbird helmforge/netbird --namespace netbird --create-namespace
OCI install:
helm install netbird oci://ghcr.io/helmforgedev/helm/netbird --namespace netbird --create-namespace
Production Example
server:
publicUrl: https://netbird.example.com
authSecret: replace-with-a-strong-random-secret
auth:
issuer: https://netbird.example.com/oauth2
store:
encryptionKey: replace-with-a-persistent-encryption-key
database:
mode: postgresql
postgresql:
enabled: true
auth:
database: netbird
username: netbird
persistence:
enabled: true
size: 20Gi
ingress:
enabled: true
ingressClassName: nginx
hosts:
- host: netbird.example.com
paths:
- path: /
pathType: Prefix
service: server
- host: dashboard.netbird.example.com
paths:
- path: /
pathType: Prefix
service: dashboard
tls:
- secretName: netbird-tls
hosts:
- netbird.example.com
- dashboard.netbird.example.com
Expose UDP 3478 for STUN with a LoadBalancer Service, Gateway implementation, or infrastructure-specific UDP listener. Kubernetes Ingress does not handle UDP.
Prefer separate hosts for production ingress: route the NetBird backend host to the server service and the dashboard host to the dashboard service. If you use one host with path-based routing, send /api, /oauth2, /relay, /ws-proxy/management, /ws-proxy/signal, /signalexchange.SignalExchange/, /management.ManagementService/, and /management.ProxyService/ to the server service before any dashboard route. Configure the ingress controller or gateway to preserve HTTP/2 or h2c behavior for gRPC routes.
External Secrets
Use External Secrets for a full upstream config.yaml or sensitive bootstrap data:
server:
config:
existingSecret: netbird-config
externalSecrets:
enabled: true
items:
- name: config
spec:
secretStoreRef:
kind: ClusterSecretStore
name: production
target:
name: netbird-config
creationPolicy: Owner
data:
- secretKey: config.yaml
remoteRef:
key: apps/netbird/config.yaml
Scaling
The v1 chart defaults to PostgreSQL through the HelmForge PostgreSQL subchart.
Use database.mode=external for a managed PostgreSQL or MySQL database. Use
database.mode=sqlite with postgresql.enabled=false only for lab or small
single-replica installs.
Even with PostgreSQL or MySQL, scaling server.replicaCount above 1 requires a complete HA topology for the combined server components. Plan signal, relay, and STUN exposure with load-balancer affinity and protocol-aware routing before enabling multiple server replicas. If that topology is not in place, keep server.replicaCount: 1.
Upgrade Notes
This v1 hardening release changes the default store from sqlite to PostgreSQL subchart mode. Existing sqlite installs that want to keep sqlite should set:
database:
mode: sqlite
postgresql:
enabled: false
To migrate production data from sqlite to PostgreSQL, follow the upstream
NetBird PostgreSQL migration guidance and back up /var/lib/netbird before
switching modes.
Dashboard replicas can scale independently when the backing server and ingress layer are ready for the traffic.