Self-Hosted Deployment Configuration Files Reference

This page provides a comprehensive reference for all configuration files used when self-hosting NetBird with the getting-started.sh deployment method. Understanding these files helps you customize your deployment, troubleshoot issues, and integrate with existing infrastructure.

Overview

A standard NetBird self-hosted deployment uses the following configuration files:

FilePurpose
docker-compose.ymlDefines all services (dashboard, netbird-server, optionally traefik), their Docker images, port mappings, volumes, and startup order. Structure varies depending on the reverse proxy option chosen during setup.
config.yamlUnified server configuration for the combined NetBird server: listen addresses, STUN, relay authentication, embedded IdP, and database settings. Replaces the old management.json and relay.env files.
dashboard.envConfigures the web dashboard including API endpoints, OAuth2/OIDC settings, and optional SSL settings for standalone deployments without a reverse proxy.

File Locations

After running the installation script, configuration files are located in the directory where you ran the script (typically ~/netbird/ or the current working directory):

./
├── docker-compose.yml
├── config.yaml
├── dashboard.env
└── nginx-netbird.conf      # Only when using Nginx reverse proxy
    npm-advanced-config.txt  # Only when using Nginx Proxy Manager
    caddyfile-netbird.txt    # Only when using Caddy reverse proxy

docker-compose.yml

The Docker Compose file defines all NetBird services, their dependencies, networking, and volumes.

Services Overview

ServiceImageInternal PortExternal (Exposed)Description
traefiktraefik:v3.680, 44380:80, 443:443Handles TLS termination via Let's Encrypt and routes incoming HTTPS requests to the appropriate NetBird services. Only included when using the built-in Traefik option (option 0).
dashboardnetbirdio/dashboard808080:80The web-based management console where administrators configure networks, manage peers, create access policies, and view activity logs. Includes an embedded nginx server for serving the UI.
netbird-servernetbirdio/netbird-server80, 3478/udp8081:80, 3478:3478/udpCombined server that includes management, signal, relay, and embedded STUN in a single container. Configured via config.yaml.

Traefik Service

The Traefik service is only present when using the built-in reverse proxy option (option 0 during setup). It handles automatic TLS certificate provisioning via Let's Encrypt and routes requests to the correct backend services.

traefik:
  image: traefik:v3.6
  container_name: netbird-traefik
  restart: unless-stopped
  networks: [netbird]
  command:
    - "--providers.docker=true"
    - "--providers.docker.exposedbydefault=false"
    - "--providers.docker.network=netbird"
    - "--entrypoints.web.address=:80"
    - "--entrypoints.websecure.address=:443"
    - "--entrypoints.websecure.transport.respondingTimeouts.readTimeout=0"
    - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
    - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
    - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
    - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
  ports:
    - '443:443'
    - '80:80'
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - netbird_traefik_letsencrypt:/letsencrypt
  logging:
    driver: "json-file"
    options:
      max-size: "500m"
      max-file: "2"

Dashboard Service

With built-in Traefik (default):

dashboard:
  image: netbirdio/dashboard:latest
  container_name: netbird-dashboard
  restart: unless-stopped
  networks: [netbird]
  env_file:
    - ./dashboard.env
  labels:
    - traefik.enable=true
    - traefik.http.routers.netbird-dashboard.rule=Host(`netbird.example.com`)
    - traefik.http.routers.netbird-dashboard.entrypoints=websecure
    - traefik.http.routers.netbird-dashboard.tls=true
    - traefik.http.routers.netbird-dashboard.tls.certresolver=letsencrypt
    - traefik.http.routers.netbird-dashboard.priority=1
    - traefik.http.services.netbird-dashboard.loadbalancer.server.port=80
  logging:
    driver: "json-file"
    options:
      max-size: "500m"
      max-file: "2"

NetBird Server Service

The combined server runs management, signal, relay, and STUN in a single container, configured by config.yaml.

With built-in Traefik (default):

netbird-server:
  image: netbirdio/netbird-server:latest
  container_name: netbird-server
  restart: unless-stopped
  networks: [netbird]
  ports:
    - '3478:3478/udp'
  volumes:
    - netbird_data:/var/lib/netbird
    - ./config.yaml:/etc/netbird/config.yaml
  command: ["--config", "/etc/netbird/config.yaml"]
  labels:
    - traefik.enable=true
    # gRPC router (needs h2c backend for HTTP/2 cleartext)
    # The /management.ProxyService/ path is only required if the reverse proxy
    # container (netbirdio/reverse-proxy) connects through Traefik — i.e., it
    # runs on a separate host or a different Docker network. If the proxy is on
    # the same Docker network as netbird-server, it connects directly and this
    # path prefix can be omitted.
    - traefik.http.routers.netbird-grpc.rule=Host(`netbird.example.com`) && (PathPrefix(`/signalexchange.SignalExchange/`) || PathPrefix(`/management.ManagementService/`) || PathPrefix(`/management.ProxyService/`))
    - traefik.http.routers.netbird-grpc.entrypoints=websecure
    - traefik.http.routers.netbird-grpc.tls=true
    - traefik.http.routers.netbird-grpc.tls.certresolver=letsencrypt
    - traefik.http.routers.netbird-grpc.service=netbird-server-h2c
    # Backend router (relay, WebSocket, API, OAuth2)
    - traefik.http.routers.netbird-backend.rule=Host(`netbird.example.com`) && (PathPrefix(`/relay`) || PathPrefix(`/ws-proxy/`) || PathPrefix(`/api`) || PathPrefix(`/oauth2`))
    - traefik.http.routers.netbird-backend.entrypoints=websecure
    - traefik.http.routers.netbird-backend.tls=true
    - traefik.http.routers.netbird-backend.tls.certresolver=letsencrypt
    - traefik.http.routers.netbird-backend.service=netbird-server
    # Services
    - traefik.http.services.netbird-server.loadbalancer.server.port=80
    - traefik.http.services.netbird-server-h2c.loadbalancer.server.port=80
    - traefik.http.services.netbird-server-h2c.loadbalancer.server.scheme=h2c
  logging:
    driver: "json-file"
    options:
      max-size: "500m"
      max-file: "2"

With external reverse proxy (exposed ports):

netbird-server:
  image: netbirdio/netbird-server:latest
  container_name: netbird-server
  restart: unless-stopped
  networks: [netbird]
  ports:
    - '127.0.0.1:8081:80'
    - '3478:3478/udp'
  volumes:
    - netbird_data:/var/lib/netbird
    - ./config.yaml:/etc/netbird/config.yaml
  command: ["--config", "/etc/netbird/config.yaml"]
  logging:
    driver: "json-file"
    options:
      max-size: "500m"
      max-file: "2"

Traefik Routing Labels

When using the built-in Traefik, the netbird-server service uses two routers to handle different traffic types:

RouterPath PrefixesBackend ServicePurpose
netbird-grpc/signalexchange.SignalExchange/, /management.ManagementService/, /management.ProxyService/netbird-server-h2c (h2c scheme)gRPC traffic for signal exchange, management API, and the Reverse Proxy feature. Uses HTTP/2 cleartext (h2c) backend because gRPC requires HTTP/2. The /management.ProxyService/ path is only needed if the reverse proxy container connects through Traefik (see comment in the snippet above).
netbird-backend/relay, /ws-proxy/, /api, /oauth2netbird-server (http scheme)HTTP traffic for relay connections, WebSocket proxying, REST API, and OAuth2/OIDC endpoints.

The dashboard router has priority=1 (lowest), so it acts as a catch-all for requests that don't match the more specific server routes.

Volume Configuration

VolumeMount PointPurpose
netbird_data/var/lib/netbirdStores the management database (SQLite by default), encryption keys, and persistent state. Back up this volume regularly to preserve your accounts, peers, policies, and setup keys.
netbird_traefik_letsencrypt/letsencryptStores Traefik's Let's Encrypt TLS certificates. Only used when deploying with the built-in Traefik reverse proxy (option 0). Preserve this volume to maintain TLS certificates across restarts.

config.yaml

The unified configuration file controls the combined NetBird server. It replaces the separate management.json and relay.env files from older deployments.

Complete Structure

server:
  listenAddress: ":80"
  exposedAddress: "https://netbird.example.com:443"
  stunPorts:
    - 3478
  metricsPort: 9090
  healthcheckAddress: ":9000"
  logLevel: "info"
  logFile: "console"

  authSecret: "your-relay-auth-secret"
  dataDir: "/var/lib/netbird"

  auth:
    issuer: "https://netbird.example.com/oauth2"
    signKeyRefreshEnabled: true
    dashboardRedirectURIs:
      - "https://netbird.example.com/nb-auth"
      - "https://netbird.example.com/nb-silent-auth"
    cliRedirectURIs:
      - "http://localhost:53000/"

  store:
    engine: "sqlite"  # sqlite, postgres, or mysql
    dsn: ""  # Connection string for postgres or mysql
    encryptionKey: "your-encryption-key"

Server Settings

  • Name
    server.listenAddress
    Type
    string
    Required
    optional
    Enum
    Description

    The address and port the combined server listens on inside the container. Default: :80. TLS is handled by the reverse proxy.

  • Name
    server.exposedAddress
    Type
    string
    Required
    optional
    Enum
    Description

    The public-facing URL where peers connect to the server. Format: https://hostname:port. This address is distributed to peers and must be reachable from all clients.

  • Name
    server.stunPorts
    Type
    array
    Required
    optional
    Enum
    Description

    List of UDP ports for the embedded STUN server. Default: [3478]. These ports must be exposed in docker-compose.yml and reachable through firewalls.

  • Name
    server.metricsPort
    Type
    number
    Required
    optional
    Enum
    Description

    Port to expose Prometheus metrics endpoint. Default: 9090. Metrics are available at /metrics for monitoring.

  • Name
    server.healthcheckAddress
    Type
    string
    Required
    optional
    Enum
    Description

    Address for health check endpoint. Default: :9000. Exposes /health for container orchestration and load balancer health probes.

  • Name
    server.logLevel
    Type
    string
    Required
    optional
    Enum
    Description

    Controls log verbosity. Options: debug, info, warn, error. Default: info. Use debug for troubleshooting connection issues.

  • Name
    server.logFile
    Type
    string
    Required
    optional
    Enum
    Description

    Where to write log output. Use console for Docker logging (recommended) or specify a file path. Default: console.

  • Name
    server.authSecret
    Type
    string
    Required
    optional
    Enum
    Description

    Shared secret for relay authentication. Auto-generated by the setup script. This secret is used internally by the combined server for relay credential validation.

  • Name
    server.dataDir
    Type
    string
    Required
    optional
    Enum
    Description

    Data directory path where the server stores its database and state files. Default: /var/lib/netbird. Maps to the netbird_data Docker volume.

Authentication Settings

Configures the built-in identity provider (embedded IdP) that handles user authentication and management.

  • Name
    server.auth.issuer
    Type
    string
    Required
    optional
    Enum
    Description

    The issuer URL for OAuth2/OIDC tokens. Format: https://your-domain/oauth2. This URL is used to validate JWT tokens and must be accessible to clients.

  • Name
    server.auth.signKeyRefreshEnabled
    Type
    boolean
    Required
    optional
    Enum
    Description

    Enables automatic refresh of IdP signing keys. Recommended: true. Ensures tokens remain valid by periodically rotating signing keys.

  • Name
    server.auth.dashboardRedirectURIs
    Type
    array
    Required
    optional
    Enum
    Description

    Allowed redirect URIs for OAuth2 authorization flow. Must include the dashboard authentication callbacks, typically /nb-auth and /nb-silent-auth on your domain.

  • Name
    server.auth.cliRedirectURIs
    Type
    array
    Required
    optional
    Enum
    Description

    Redirect URIs for CLI-based authentication. Default: ["http://localhost:53000/"]. Used when authenticating via the netbird CLI tool.

When the embedded IdP is active, the server automatically hosts these OIDC endpoints:

  • Discovery: https://your-domain/oauth2/.well-known/openid-configuration
  • JWKS (signing keys): https://your-domain/oauth2/keys
  • Token issuance: https://your-domain/oauth2/token
  • Device authorization: https://your-domain/oauth2/device/authorize

Store Settings

Configures the database backend for storing all NetBird management data including accounts, peers, groups, access policies, routes, DNS configuration, setup keys, and activity logs.

  • Name
    server.store.engine
    Type
    string
    Required
    optional
    Enum
    Description

    Database engine. Options: sqlite, postgres, mysql. Default: sqlite.

  • Name
    server.store.dsn
    Type
    string
    Required
    optional
    Enum
    Description

    Connection string for postgres or mysql engines. For postgres: host=localhost user=netbird password=secret dbname=netbird port=5432. Alternatively, use the NETBIRD_STORE_ENGINE_POSTGRES_DSN or NETBIRD_STORE_ENGINE_MYSQL_DSN environment variables.

  • Name
    server.store.encryptionKey
    Type
    string
    Required
    optional
    Enum
    Description

    32-byte (256-bit) encryption key for sensitive data at rest. Used to encrypt setup keys, API tokens, and other secrets stored in the database. Auto-generated by the setup script.

What data is stored?

  • Accounts and users - User accounts, roles, and permissions
  • Peers - Registered devices, their WireGuard keys, IP assignments, and metadata
  • Groups - Peer groupings used for access control
  • Access policies - Network access rules
  • Routes - Network routes for external subnets
  • DNS configuration - Custom DNS settings
  • Setup keys - Keys for automated peer enrollment
  • Activity logs - Audit trail
EngineStorageNotes
SQLite (default)/var/lib/netbird/ volumeFile-based database stored in the netbird_data Docker volume. Zero configuration required, but does not support concurrent writes or running multiple management instances. Best for testing or small deployments.
PostgreSQLExternal database serverRecommended for production deployments. Supports concurrent access, enabling multiple management instances for high availability.
MySQLExternal database serverAlternative to PostgreSQL for organizations that have standardized on MySQL/MariaDB. Provides similar benefits including concurrent access.

For PostgreSQL or MySQL, set the connection string via the server.store.dsn field in config.yaml or environment variables on the netbird-server container. See Using an External Database below.

See Management Postgres Store for detailed PostgreSQL setup.


dashboard.env

Environment configuration for the dashboard service.

Dashboard Architecture

The NetBird dashboard container includes an embedded nginx server that serves the dashboard web pages. This nginx instance is built into the container image and handles serving the static web UI files.

# Endpoints
NETBIRD_MGMT_API_ENDPOINT=https://netbird.example.com
NETBIRD_MGMT_GRPC_API_ENDPOINT=https://netbird.example.com

# OIDC - using embedded IdP
AUTH_AUDIENCE=netbird-dashboard
AUTH_CLIENT_ID=netbird-dashboard
AUTH_CLIENT_SECRET=
AUTH_AUTHORITY=https://netbird.example.com/oauth2
USE_AUTH0=false
AUTH_SUPPORTED_SCOPES=openid profile email groups
AUTH_REDIRECT_URI=/nb-auth
AUTH_SILENT_REDIRECT_URI=/nb-silent-auth

# SSL - disabled when behind reverse proxy (Traefik handles TLS)
NGINX_SSL_PORT=443
LETSENCRYPT_DOMAIN=none

Endpoint Configuration

VariableDescription
NETBIRD_MGMT_API_ENDPOINTThe URL where the dashboard makes REST API calls to the management server (e.g., https://netbird.example.com). Must be accessible from users' browsers since API calls are made client-side.
NETBIRD_MGMT_GRPC_API_ENDPOINTThe URL for gRPC communication with the management server. Usually the same as the REST endpoint. Used for in-browser SSH and RDP clients, as well as surfacing management links for client config instructions.

Authentication Configuration

VariableDescription
AUTH_AUDIENCEThe expected audience claim in OAuth2 tokens. Must match the audience configured in your IdP. For embedded IdP, use netbird-dashboard.
AUTH_CLIENT_IDThe OAuth2 client identifier for the dashboard application. For embedded IdP deployments, this is netbird-dashboard. Must match the client ID registered with your identity provider.
AUTH_CLIENT_SECRETOAuth2 client secret for confidential clients. Leave empty for public clients (the default for browser-based apps like the dashboard).
AUTH_AUTHORITYThe OAuth2/OIDC issuer URL (e.g., https://netbird.example.com/oauth2 for embedded IdP). The dashboard fetches OIDC discovery metadata from {AUTH_AUTHORITY}/.well-known/openid-configuration.
USE_AUTH0Set to true only when using Auth0 as your identity provider. Leave as false for embedded IdP or other OIDC providers.
AUTH_SUPPORTED_SCOPESSpace-separated list of OAuth2 scopes to request during login. Standard value is openid profile email groups.
AUTH_REDIRECT_URIThe path where the IdP redirects after authentication (e.g., /nb-auth). Must match a redirect URI registered with your identity provider.
AUTH_SILENT_REDIRECT_URIThe path for silent token refresh (e.g., /nb-silent-auth). Used by the dashboard to refresh tokens in the background without user interaction.

Embedded Nginx Configuration

The dashboard container's embedded nginx server can be configured using these environment variables. These settings control how the dashboard serves its web UI.

VariableDefaultDescription
NGINX_SSL_PORT443The HTTPS port for the dashboard's embedded nginx server. Only relevant in standalone mode without an external reverse proxy.
LETSENCRYPT_DOMAIN-The domain name for automatic Let's Encrypt certificate provisioning. Set to none when using an external reverse proxy that handles TLS.
LETSENCRYPT_EMAIL-Email address for Let's Encrypt account registration and certificate expiry notifications. Required when LETSENCRYPT_DOMAIN is set to an actual domain.

Common Configuration Scenarios

Using an External Database

To use PostgreSQL instead of SQLite:

  1. Update config.yaml:
server:
  store:
    engine: "postgres"
    dsn: "host=db-server user=netbird password=secret dbname=netbird port=5432"

Alternatively, you can use an environment variable instead of putting the DSN in the config file:

netbird-server:
  environment:
    - NETBIRD_STORE_ENGINE_POSTGRES_DSN=host=db-server user=netbird password=secret dbname=netbird port=5432
    # Or for MySQL:
    # - NETBIRD_STORE_ENGINE_MYSQL_DSN=user:password@tcp(host:3306)/netbird

See Management Postgres Store for detailed setup.

Changing Log Level

Update server.logLevel in config.yaml:

server:
  logLevel: "debug"

Options: debug, info, warn, error. Use debug for troubleshooting connection issues.

Custom STUN Ports

To use multiple STUN ports, update config.yaml:

server:
  stunPorts:
    - 3478
    - 3479

Make sure to expose all ports in docker-compose.yml:

netbird-server:
  ports:
    - '3478:3478/udp'
    - '3479:3479/udp'

Behind a Reverse Proxy

When running behind your own reverse proxy (Nginx, Caddy, Nginx Proxy Manager, etc.) instead of the built-in Traefik:

  1. Set LETSENCRYPT_DOMAIN=none in dashboard.env
  2. Use the exposed-ports variant of docker-compose.yml (the setup script generates this automatically for options 1-4)
  3. Configure your reverse proxy to route traffic to the correct containers and ports:
    • Dashboard: 127.0.0.1:8080 (HTTP)
    • NetBird Server: 127.0.0.1:8081 (HTTP), with gRPC paths using h2c (HTTP/2 cleartext)

See External Reverse Proxy Configuration for detailed templates for Nginx, Caddy, and other proxies.

Using External Services (Advanced)

To use external STUN, relay, or signal servers, add overrides to config.yaml:

server:
  # ... basic settings ...

  # Optional: Use external STUN servers
  stuns:
    - uri: "stun:stun.example.com:3478"
      proto: "udp"

  # Optional: Use external relay servers
  relays:
    addresses:
      - "rels://relay.example.com:443"
    secret: "relay-auth-secret"
    credentialsTTL: "24h"

  # Optional: Use external signal server
  signalUri: "https://signal.example.com:443"

See the Scaling Your Self-Hosted Deployment guide for more details on configuring external services.


See Also