docker.recipes

NetBird Mesh VPN

advanced

Open source WireGuard-based mesh VPN with zero-config, identity provider integration.

Overview

NetBird is a WireGuard-based mesh VPN solution that eliminates traditional VPN complexity through zero-configuration peer-to-peer networking. Built on modern zero-trust principles, NetBird creates encrypted tunnels between devices without requiring manual key exchanges or complex routing configurations. The platform emerged as an open-source alternative to proprietary mesh VPN solutions, leveraging WireGuard's proven cryptography while adding intelligent peer discovery and management capabilities. This deployment combines NetBird's management server with its signaling infrastructure, TURN relay services via Coturn, and PostgreSQL for persistent configuration storage. The management component handles device enrollment, policy enforcement, and network topology decisions, while the signal server facilitates peer discovery and initial connection establishment. Coturn provides STUN/TURN relay capabilities for devices behind restrictive NATs, ensuring connectivity even in challenging network environments. NGINX serves as the web interface proxy and handles SSL termination for the management dashboard. This stack is ideal for organizations seeking modern VPN infrastructure without the overhead of traditional hub-and-spoke architectures. IT teams managing remote workforces, developers requiring secure access to distributed development environments, and organizations implementing zero-trust network models will find NetBird's approach particularly valuable. The integration with identity providers through OIDC support makes it suitable for enterprises with existing SSO infrastructure.

Key Features

  • WireGuard-based mesh networking with automatic peer discovery and key rotation
  • Zero-configuration client deployment with automated network topology management
  • OIDC integration supporting major identity providers including Google, Azure AD, and Okta
  • Real-time peer connection status monitoring through PostgreSQL-backed management interface
  • STUN/TURN relay support via Coturn for NAT traversal in restrictive network environments
  • Single account mode for simplified small-team deployments without external identity providers
  • Policy-based access control with granular network segmentation capabilities
  • Cross-platform client support with automatic updates and configuration synchronization

Common Use Cases

  • 1Remote team secure access to internal development environments and staging servers
  • 2Site-to-site connectivity for distributed offices without dedicated VPN appliances
  • 3Secure IoT device management and monitoring across multiple geographic locations
  • 4Development team collaboration requiring encrypted communication between workstations
  • 5Freelancer and contractor access management with time-limited network permissions
  • 6Home lab enthusiasts connecting personal devices across different network locations
  • 7Small business secure file sharing and printer access for remote employees

Prerequisites

  • Public domain name with DNS control for SSL certificate generation and client discovery
  • Minimum 2GB RAM and 20GB storage for production deployments with active peer management
  • Firewall configuration allowing UDP 3478 for TURN relay and TCP 443/10000 for management services
  • Basic understanding of WireGuard networking concepts and IP address allocation
  • OIDC provider credentials if using SSO integration instead of single account mode
  • SSL certificate management capability for HTTPS-enabled management interface

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 management:
3 image: netbirdio/management:latest
4 environment:
5 NETBIRD_DOMAIN: ${NETBIRD_DOMAIN}
6 NETBIRD_MGMT_API_ENDPOINT: https://${NETBIRD_DOMAIN}:443
7 NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN: ${NETBIRD_DOMAIN}
8 ports:
9 - "443:443"
10 volumes:
11 - management:/var/lib/netbird
12 - ./management.json:/etc/netbird/management.json:ro
13 depends_on:
14 postgres:
15 condition: service_healthy
16 networks:
17 - netbird-net
18 restart: unless-stopped
19
20 signal:
21 image: netbirdio/signal:latest
22 ports:
23 - "10000:80"
24 networks:
25 - netbird-net
26 restart: unless-stopped
27
28 coturn:
29 image: coturn/coturn:latest
30 command: -c /etc/turnserver.conf
31 ports:
32 - "3478:3478/udp"
33 - "3478:3478/tcp"
34 volumes:
35 - ./turnserver.conf:/etc/turnserver.conf:ro
36 networks:
37 - netbird-net
38 restart: unless-stopped
39
40 postgres:
41 image: postgres:15-alpine
42 environment:
43 POSTGRES_USER: ${POSTGRES_USER}
44 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
45 POSTGRES_DB: ${POSTGRES_DB}
46 volumes:
47 - postgres_data:/var/lib/postgresql/data
48 healthcheck:
49 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
50 interval: 10s
51 timeout: 5s
52 retries: 5
53 networks:
54 - netbird-net
55 restart: unless-stopped
56
57 nginx:
58 image: nginx:alpine
59 ports:
60 - "80:80"
61 volumes:
62 - ./nginx.conf:/etc/nginx/nginx.conf:ro
63 depends_on:
64 - management
65 networks:
66 - netbird-net
67 restart: unless-stopped
68
69volumes:
70 management:
71 postgres_data:
72
73networks:
74 netbird-net:
75 driver: bridge

.env Template

.env
1# NetBird Domain
2NETBIRD_DOMAIN=netbird.example.com
3
4# PostgreSQL
5POSTGRES_USER=netbird
6POSTGRES_PASSWORD=secure_postgres_password
7POSTGRES_DB=netbird
8
9# TURN Server
10TURN_SECRET=your_turn_secret_here

Usage Notes

  1. 1Dashboard at https://netbird.example.com
  2. 2Supports SSO with OIDC providers
  3. 3Clients auto-discover and connect via signal server
  4. 4TURN server handles NAT traversal

Individual Services(5 services)

Copy individual services to mix and match with your existing compose files.

management
management:
  image: netbirdio/management:latest
  environment:
    NETBIRD_DOMAIN: ${NETBIRD_DOMAIN}
    NETBIRD_MGMT_API_ENDPOINT: https://${NETBIRD_DOMAIN}:443
    NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN: ${NETBIRD_DOMAIN}
  ports:
    - "443:443"
  volumes:
    - management:/var/lib/netbird
    - ./management.json:/etc/netbird/management.json:ro
  depends_on:
    postgres:
      condition: service_healthy
  networks:
    - netbird-net
  restart: unless-stopped
signal
signal:
  image: netbirdio/signal:latest
  ports:
    - "10000:80"
  networks:
    - netbird-net
  restart: unless-stopped
coturn
coturn:
  image: coturn/coturn:latest
  command: "-c /etc/turnserver.conf"
  ports:
    - 3478:3478/udp
    - 3478:3478/tcp
  volumes:
    - ./turnserver.conf:/etc/turnserver.conf:ro
  networks:
    - netbird-net
  restart: unless-stopped
postgres
postgres:
  image: postgres:15-alpine
  environment:
    POSTGRES_USER: ${POSTGRES_USER}
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    POSTGRES_DB: ${POSTGRES_DB}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  healthcheck:
    test:
      - CMD-SHELL
      - pg_isready -U ${POSTGRES_USER}
    interval: 10s
    timeout: 5s
    retries: 5
  networks:
    - netbird-net
  restart: unless-stopped
nginx
nginx:
  image: nginx:alpine
  ports:
    - "80:80"
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
  depends_on:
    - management
  networks:
    - netbird-net
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 management:
5 image: netbirdio/management:latest
6 environment:
7 NETBIRD_DOMAIN: ${NETBIRD_DOMAIN}
8 NETBIRD_MGMT_API_ENDPOINT: https://${NETBIRD_DOMAIN}:443
9 NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN: ${NETBIRD_DOMAIN}
10 ports:
11 - "443:443"
12 volumes:
13 - management:/var/lib/netbird
14 - ./management.json:/etc/netbird/management.json:ro
15 depends_on:
16 postgres:
17 condition: service_healthy
18 networks:
19 - netbird-net
20 restart: unless-stopped
21
22 signal:
23 image: netbirdio/signal:latest
24 ports:
25 - "10000:80"
26 networks:
27 - netbird-net
28 restart: unless-stopped
29
30 coturn:
31 image: coturn/coturn:latest
32 command: -c /etc/turnserver.conf
33 ports:
34 - "3478:3478/udp"
35 - "3478:3478/tcp"
36 volumes:
37 - ./turnserver.conf:/etc/turnserver.conf:ro
38 networks:
39 - netbird-net
40 restart: unless-stopped
41
42 postgres:
43 image: postgres:15-alpine
44 environment:
45 POSTGRES_USER: ${POSTGRES_USER}
46 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
47 POSTGRES_DB: ${POSTGRES_DB}
48 volumes:
49 - postgres_data:/var/lib/postgresql/data
50 healthcheck:
51 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
52 interval: 10s
53 timeout: 5s
54 retries: 5
55 networks:
56 - netbird-net
57 restart: unless-stopped
58
59 nginx:
60 image: nginx:alpine
61 ports:
62 - "80:80"
63 volumes:
64 - ./nginx.conf:/etc/nginx/nginx.conf:ro
65 depends_on:
66 - management
67 networks:
68 - netbird-net
69 restart: unless-stopped
70
71volumes:
72 management:
73 postgres_data:
74
75networks:
76 netbird-net:
77 driver: bridge
78EOF
79
80# 2. Create the .env file
81cat > .env << 'EOF'
82# NetBird Domain
83NETBIRD_DOMAIN=netbird.example.com
84
85# PostgreSQL
86POSTGRES_USER=netbird
87POSTGRES_PASSWORD=secure_postgres_password
88POSTGRES_DB=netbird
89
90# TURN Server
91TURN_SECRET=your_turn_secret_here
92EOF
93
94# 3. Start the services
95docker compose up -d
96
97# 4. View logs
98docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/netbird-vpn-stack/run | bash

Troubleshooting

  • Clients unable to connect through NAT: Verify Coturn TURN server is accessible on UDP 3478 and check firewall rules for STUN/TURN traffic
  • Management interface shows 502 Bad Gateway: Check PostgreSQL container health status and verify database connection string in management.json configuration
  • Peer discovery failing in signal server: Ensure NetBird domain environment variable matches your public DNS name and signal service is reachable on port 10000
  • OIDC authentication redirects failing: Verify callback URLs in identity provider match your NetBird domain and check management container logs for authentication errors
  • PostgreSQL connection refused errors: Confirm POSTGRES_USER and POSTGRES_PASSWORD environment variables match between management and postgres services
  • WireGuard tunnel established but no traffic flowing: Check IP address allocation conflicts and verify routing table entries on NetBird clients

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space