Netbird VPN Installation and Configuration
NetBird is a WireGuard-based mesh VPN platform that automatically establishes encrypted peer-to-peer connections between devices without manual WireGuard key exchange. With a self-hosted management server, SSO integration, ACL policies, and network routes, NetBird provides zero-config secure networking for distributed Linux infrastructure.
Prerequisites
- A VPS for the management server (at least 1 GB RAM)
- Ubuntu/Debian or CentOS/Rocky on all nodes
- Docker and Docker Compose on the management server
- A domain name for the management server
- Ports 80, 443, 33073 (management), and 10000 (Signal) open
Self-Hosted Management Server Setup
# Clone the NetBird management setup
git clone https://github.com/netbirdio/netbird.git
cd netbird/infrastructure_files
# Or use the quickstart script
export NETBIRD_DOMAIN="netbird.yourdomain.com"
export NETBIRD_AUTH_AUTHORITY="none" # Use built-in auth
export NETBIRD_AUTH_JWT_CERTS="https://netbird.yourdomain.com/.well-known/jwks.json"
# Download and configure
curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/netbird_management_linux_amd64.tar.gz | \
tar -xz
Docker Compose Deployment
# docker-compose.yml for NetBird management server
version: '3'
services:
# Coturn STUN/TURN server
coturn:
image: coturn/coturn
network_mode: host
volumes:
- ./turnserver.conf:/etc/turnserver.conf
command: ["-c", "/etc/turnserver.conf"]
restart: unless-stopped
# Signal server
signal:
image: netbirdio/signal:latest
ports:
- "10000:10000"
restart: unless-stopped
volumes:
- netbird-signal:/var/lib/netbird
# Management server
management:
image: netbirdio/management:latest
ports:
- "33073:33073"
- "33071:33071"
volumes:
- netbird-mgmt:/var/lib/netbird
- ./management.json:/etc/netbird/management.json
environment:
- NETBIRD_STORE_ENGINE=sqlite
command: [
"--port", "33073",
"--log-file", "console",
"--single-account-mode-domain", "netbird.yourdomain.com",
"--dns-domain", "netbird.yourdomain.com"
]
restart: unless-stopped
# Dashboard
dashboard:
image: netbirdio/dashboard:latest
ports:
- "80:80"
- "443:443"
environment:
- NETBIRD_MGMT_API_ENDPOINT=https://netbird.yourdomain.com:33073
- NETBIRD_SIGNAL_URI=grpcs://netbird.yourdomain.com:10000
- AUTH_AUTHORITY=https://netbird.yourdomain.com
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
restart: unless-stopped
volumes:
netbird-signal:
netbird-mgmt:
# Start the management stack
docker compose up -d
# Check all services are running
docker compose ps
# View management server logs
docker compose logs management --tail 50 -f
Installing the NetBird Client
# Ubuntu/Debian
curl -fsSL https://pkgs.netbird.io/install.sh | sudo bash
# CentOS/Rocky
curl -fsSL https://pkgs.netbird.io/install.sh | sudo bash
# Or install via APT directly
curl -sSL https://pkgs.netbird.io/debian/public.key | sudo gpg --dearmor -o /usr/share/keyrings/netbird-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/netbird-archive-keyring.gpg] https://pkgs.netbird.io/debian stable main' | \
sudo tee /etc/apt/sources.list.d/netbird.list
sudo apt-get update
sudo apt-get install -y netbird
# Verify installation
netbird version
Peer Configuration and Login
# Connect to your self-hosted management server
sudo netbird up \
--management-url https://netbird.yourdomain.com:33073 \
--admin-url https://netbird.yourdomain.com
# For hosted NetBird (app.netbird.io)
sudo netbird up
# The command will output a setup key URL or SSO login URL
# Open the URL in a browser to authenticate
# Login with a setup key (for headless/automated registration)
sudo netbird up \
--management-url https://netbird.yourdomain.com:33073 \
--setup-key YOUR-SETUP-KEY
# Check connection status
sudo netbird status
sudo netbird status --detail
After connecting, each peer gets a NetBird IP (default range: 100.64.0.0/10):
# Check assigned IP
sudo netbird status | grep "NetBird IP"
# Test connectivity between peers
ping 100.64.0.2 # Replace with peer's NetBird IP
# Check WireGuard interface
ip addr show wt0
wg show wt0
ACL Policies
NetBird uses policies to control which peers can communicate with each other:
# List current policies via API
curl -s "https://netbird.yourdomain.com/api/policies" \
-H "Authorization: Token your-api-token" | python3 -m json.tool
# Create a policy allowing web servers to talk to database servers
curl -X POST "https://netbird.yourdomain.com/api/policies" \
-H "Authorization: Token your-api-token" \
-H "Content-Type: application/json" \
-d '{
"name": "WebDB Access",
"description": "Allow web servers to reach database servers",
"enabled": true,
"rules": [
{
"name": "web-to-db",
"enabled": true,
"action": "accept",
"bidirectional": false,
"protocol": "tcp",
"ports": ["5432", "3306"],
"sources": [{"id": "web-servers-group-id"}],
"destinations": [{"id": "db-servers-group-id"}]
}
]
}'
Managing Groups
# Create a peer group
curl -X POST "https://netbird.yourdomain.com/api/groups" \
-H "Authorization: Token your-api-token" \
-H "Content-Type: application/json" \
-d '{
"name": "web-servers",
"peers": ["peer-id-1", "peer-id-2"]
}'
# List peers
curl -s "https://netbird.yourdomain.com/api/peers" \
-H "Authorization: Token your-api-token"
# Add peer to a group
curl -X PUT "https://netbird.yourdomain.com/api/groups/group-id" \
-H "Authorization: Token your-api-token" \
-H "Content-Type: application/json" \
-d '{"name": "web-servers", "peers": ["peer-id-1", "peer-id-2", "peer-id-3"]}'
SSO Integration
Configure SSO so team members log in with existing credentials:
# NetBird supports:
# - Google Workspace
# - Okta
# - Azure AD / Entra ID
# - Auth0
# - Keycloak (self-hosted)
# Configure in management.json
cat > management.json << 'EOF'
{
"AuthClaims": {
"UserIDClaim": "sub",
"GroupsClaim": "groups"
},
"IdpManagerConfig": {
"ManagerType": "auth0",
"ClientConfig": {
"Issuer": "https://your-tenant.auth0.com",
"ClientID": "your-client-id",
"ClientSecret": "your-client-secret",
"GrantType": "client_credentials",
"TokenEndpoint": "https://your-tenant.auth0.com/oauth/token",
"Audience": "https://your-tenant.auth0.com/api/v2/"
}
}
}
EOF
Network Routes
NetBird can route traffic to non-NetBird networks through designated peers:
# Add a route to reach an on-premises network (e.g., 192.168.1.0/24)
# through a gateway peer
curl -X POST "https://netbird.yourdomain.com/api/routes" \
-H "Authorization: Token your-api-token" \
-H "Content-Type: application/json" \
-d '{
"description": "On-premises network",
"network_id": "onprem-01",
"enabled": true,
"peer": "gateway-peer-id",
"network": "192.168.1.0/24",
"metric": 9999,
"masquerade": true,
"groups": ["all-peers-group-id"]
}'
# On the gateway peer, enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
Managing Peers via CLI
# View detailed peer status
sudo netbird status --detail
# Bring the NetBird interface down
sudo netbird down
# Bring it back up
sudo netbird up --management-url https://netbird.yourdomain.com:33073
# View WireGuard configuration
sudo cat /etc/wireguard/wt0.conf
# Check NetBird daemon logs
sudo journalctl -u netbird -f
# Get peer list from management server
sudo netbird peers list
Troubleshooting
Peer shows "Disconnected" in dashboard:
# Check client is running
sudo systemctl status netbird
# Check management server connectivity
curl -I https://netbird.yourdomain.com:33073
# View connection errors
sudo journalctl -u netbird --since "1 hour ago" | grep -i error
Cannot ping other peers:
# Verify both peers are connected to management
sudo netbird status
# Check ACL policy allows communication
# Verify peers are in the same or allowed groups
# Check WireGuard interface
wg show wt0
ip route | grep wt0
Management server port 33073 not accessible:
# Check firewall
sudo ufw allow 33073/tcp
# Check Docker port binding
docker ps | grep management
netstat -tlnp | grep 33073
Conclusion
NetBird simplifies WireGuard mesh networking by automating key exchange and peer discovery, eliminating the manual configuration that makes traditional WireGuard deployments complex. With a self-hosted management server, SSO integration, and granular ACL policies, it provides enterprise-grade zero-trust networking for Linux infrastructure without relying on any external cloud services.


