The fastest way to deploy NetBird is using Docker Compose with the automated getting-started script. This method sets up all required services with a single command.
Prerequisites
Before starting, ensure you have:
Linux Server
A Linux VM with at least 1 CPU and 2GB RAM . The server must be publicly accessible on:
TCP ports 80 and 443 (HTTPS)
UDP port 3478 (STUN)
Domain Name
A public domain name pointing to your server’s IP address (e.g., netbird.example.com)
Docker Installed
Install Docker with docker-compose plugin: # Install Docker (Ubuntu/Debian)
curl -fsSL https://get.docker.com | sh
# Verify installation
docker --version
docker compose version
Required Utilities
Install jq and curl: # Debian/Ubuntu
sudo apt update && sudo apt install jq curl
# RHEL/CentOS
sudo yum install jq curl
Quick Start (Recommended)
The getting-started.sh script automates the entire deployment process:
export NETBIRD_DOMAIN = netbird . example . com
curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bash
What the Script Does
The script will:
Validate requirements - Check for Docker, jq, and curl
Prompt for configuration - Ask about reverse proxy preferences
Generate configurations - Create docker-compose.yml, config.yaml, and dashboard.env
Generate secrets - Create encryption keys and relay auth secrets
Start services - Launch all containers with proper networking
Configure TLS - Set up automatic HTTPS via Let’s Encrypt (with Traefik)
The entire process takes about 2-3 minutes. You’ll be able to access the dashboard immediately after completion.
Interactive Setup Process
Step 1: Domain Configuration
If NETBIRD_DOMAIN is not set, the script will prompt:
Enter the domain you want to use for NetBird (e.g. netbird.my-domain.com ):
Do not use netbird.example.com or localhost. You need a real domain name pointing to your server.
Step 2: Reverse Proxy Selection
Choose your reverse proxy configuration:
Which reverse proxy will you use?
[0] Traefik (recommended - automatic TLS, included in Docker Compose )
[1] Existing Traefik (labels for external Traefik instance )
[2] Nginx (generates config template )
[3] Nginx Proxy Manager (generates config + instructions )
[4] External Caddy (generates Caddyfile snippet )
[5] Other/Manual (displays setup documentation )
Enter choice [0-5] ( default: 0 ):
Option 0: Built-in Traefik (Recommended)
The simplest option - includes Traefik in the Docker Compose stack:
Automatic TLS via Let’s Encrypt
No manual certificate management
HTTP to HTTPS redirect configured
gRPC support for signal and management services
You’ll be prompted for:
Enter your email for Let's Encrypt certificate notifications.
Email address: [email protected]
Do you want to enable the NetBird Proxy service?
Enable proxy? [y/N]:
What is the Proxy service?
The NetBird Proxy allows you to selectively expose internal network resources to the internet. It’s optional and can be enabled later if needed. If enabled, you’ll need to:
Provide a separate domain (e.g., proxy.example.com)
Add a wildcard DNS record (*.proxy.example.com)
Open UDP port 51820 for WireGuard connections
Option 1: External Traefik
For integration with an existing Traefik instance:
External network (leave empty to create 'netbird' network ): traefik-public
HTTPS entrypoint name (default: websecure ):
Certificate resolver name (e.g., letsencrypt ):
The script generates Docker labels for Traefik to discover services automatically.
Options 2-4: External Proxies
For Nginx, Nginx Proxy Manager, or Caddy, the script:
Generates proxy configuration files
Exposes container ports (bound to localhost or 0.0.0.0)
Provides setup instructions
You’ll need to manually configure TLS certificates.
Option 5: Manual/Custom
Generates basic docker-compose.yml with exposed ports and displays configuration requirements.
Generated Files
After running the script, you’ll have:
docker-compose.yml
The main orchestration file with services:
services :
# Traefik reverse proxy (if using option 0)
traefik :
image : traefik:v3.6
ports :
- '443:443'
- '80:80'
# ... Traefik configuration
# NetBird Dashboard
dashboard :
image : netbirdio/dashboard:latest
env_file :
- ./dashboard.env
# ... Labels and networking
# Combined NetBird Server (Management + Signal + Relay + STUN)
netbird-server :
image : netbirdio/netbird-server:latest
ports :
- '3478:3478/udp' # STUN
volumes :
- netbird_data:/var/lib/netbird
- ./config.yaml:/etc/netbird/config.yaml
# ... Labels and configuration
volumes :
netbird_data :
netbird_traefik_letsencrypt :
networks :
netbird :
driver : bridge
ipam :
config :
- subnet : 172.30.0.0/24
config.yaml
Combined server configuration:
server :
listenAddress : ":80"
exposedAddress : "https://netbird.example.com:443"
stunPorts :
- 3478
metricsPort : 9090
healthcheckAddress : ":9000"
logLevel : "info"
logFile : "console"
authSecret : "<generated-relay-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/"
reverseProxy :
trustedHTTPProxies :
- "172.30.0.10/32" # Traefik IP
store :
engine : "sqlite"
encryptionKey : "<generated-encryption-key>"
The encryptionKey encrypts sensitive data in the database. Back up this file - you cannot recover encrypted data without it.
dashboard.env
Dashboard environment variables:
# API Endpoints
NETBIRD_MGMT_API_ENDPOINT = https://netbird.example.com
NETBIRD_MGMT_GRPC_API_ENDPOINT = https://netbird.example.com
# OAuth Configuration (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
Managing the Deployment
Starting Services
The script starts services automatically, but you can manage them manually:
# Start all services
docker compose up -d
# Start specific service
docker compose up -d netbird-server
# View logs
docker compose logs -f netbird-server
# View all logs
docker compose logs -f
Stopping Services
# Stop all services (keeps volumes)
docker compose down
# Stop and remove volumes (deletes all data)
docker compose down --volumes
Using --volumes will delete all peer data, access policies, and user accounts. Only use this for complete reinstallation.
Updating NetBird
# Pull latest images
docker compose pull
# Restart services with new images
docker compose up -d
Viewing Service Status
# Check running containers
docker compose ps
# Check resource usage
docker stats
# View logs for specific service
docker compose logs --tail=100 netbird-server
Post-Installation
Accessing the Dashboard
Once services are running, access the dashboard:
https://netbird.example.com
The first access will:
Redirect to the embedded OAuth2 provider
Show the onboarding wizard
Create the first admin account
Verifying Services
Check that all services are healthy:
# Check server health
curl -k https://netbird.example.com/api/health
# Check OAuth configuration
curl -k https://netbird.example.com/oauth2/.well-known/openid-configuration
# Check container health
docker compose ps
Network Ports
Verify required ports are accessible:
# From external machine, test HTTPS
curl -I https://netbird.example.com
# Test STUN port (from peer machine)
netbird status
Troubleshooting
Certificate Issues
If Let’s Encrypt certificate generation fails:
# Check Traefik logs
docker compose logs traefik
# Verify DNS resolution
nslookup netbird.example.com
# Verify port 80 and 443 are accessible
curl -I http://netbird.example.com
Let’s Encrypt requires ports 80 and 443 to be publicly accessible. Check firewall rules and DNS propagation.
Service Not Starting
# Check logs for errors
docker compose logs netbird-server
# Verify configuration syntax
docker compose config
# Check port conflicts
sudo netstat -tulpn | grep -E ':(80|443|3478)\s'
Database Errors
# Check volume permissions
docker compose exec netbird-server ls -la /var/lib/netbird
# Reset database (WARNING: deletes all data)
docker compose down
docker volume rm netbird_data
docker compose up -d
Reinitializing Setup
To completely reset and reconfigure:
# Stop services and remove volumes
docker compose down --volumes
# Remove generated configuration files
rm -f docker-compose.yml dashboard.env config.yaml \
proxy.env traefik-dynamic.yaml nginx-netbird.conf \
caddyfile-netbird.txt npm-advanced-config.txt
# Run setup script again
export NETBIRD_DOMAIN = netbird . example . com
curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bash
Advanced Configuration
Using External Database
To use PostgreSQL or MySQL instead of SQLite, edit config.yaml:
server :
store :
engine : "postgres"
# encryptionKey is still required
Then set environment variable in docker-compose.yml:
netbird-server :
environment :
- NETBIRD_STORE_ENGINE_POSTGRES_DSN=host=postgres user=netbird password=secret dbname=netbird port=5432
Custom Identity Provider
For advanced IdP setup (Auth0, Keycloak, Zitadel), use the alternative scripts:
# Zitadel
curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started-with-zitadel.sh | bash
# Custom IdP with configure.sh
cp infrastructure_files/setup.env.example setup.env
# Edit setup.env with your IdP details
bash infrastructure_files/configure.sh
See Identity Providers for detailed configuration.
Port Binding Options
By default, with external proxies, ports are bound to 127.0.0.1 for security:
ports :
- '127.0.0.1:8080:80' # Dashboard
- '127.0.0.1:8081:80' # NetBird server
If your reverse proxy is on a different host, bind to 0.0.0.0:
ports :
- '8080:80'
- '8081:80'
Binding to 0.0.0.0 exposes services to the network. Ensure proper firewall rules are in place.
Next Steps
Install Clients Install NetBird clients on your devices
Access Control Configure access policies and network rules
DNS Management Set up private DNS for your network
Routing Configure routes to external networks