NetBird: Self-Hosted WireGuard Mesh VPN for Your Homelab
If you've used Tailscale, you already know how nice mesh VPNs are — install on two machines, they find each other, done. But Tailscale's coordination server is a third-party service. NetBird gives you the same experience with a self-hosted control plane, so your network topology never leaves your infrastructure.
What NetBird Actually Does
NetBird builds WireGuard tunnels between your devices automatically. Each device runs a lightweight agent that registers with a management server. The management server handles peer discovery, NAT traversal (via STUN/TURN), and access policies. The actual traffic flows directly between peers — the server only coordinates connections.
This matters for homelabs because you probably have machines in multiple places: a Proxmox host at home, a VPS for public services, a laptop that moves between networks, maybe a remote backup server. NetBird connects all of them into a flat network where every device can reach every other device by its NetBird IP.
Self-Hosted vs Tailscale vs Headscale
You might be wondering why not just use Tailscale or Headscale. Here's the practical difference:
Tailscale is the easiest option. Sign up, install, done. But your coordination data lives on Tailscale's servers, free tier has device limits, and you're trusting a third party with your network graph.
Headscale is an open-source reimplementation of the Tailscale coordination server. It works well, but it's reverse-engineered — it tracks Tailscale's protocol changes rather than defining its own. Client compatibility can break when Tailscale updates their client.
NetBird is purpose-built for self-hosting from the start. The management server, signal server, and relay (TURN) are all open source and designed to run together. You get a web UI for managing peers and access policies, SSO integration, and the full control plane on your own hardware.
Deploying the Management Server
The fastest way is Docker Compose. You'll need a machine with a public IP or at least a domain pointing to it — peers need to reach the management and signal servers to establish connections.
Create a directory and grab the official compose file:
mkdir ~/netbird && cd ~/netbird
curl -fsSL https://raw.githubusercontent.com/netbirdio/netbird/main/infrastructure_files/getting-started-with-zitadel.sh -o setup.sh
chmod +x setup.sh
The setup script configures NetBird with Zitadel as the identity provider (it runs alongside NetBird in the same compose stack). Run it with your domain:
./setup.sh --domain vpn.example.com
This generates a docker-compose.yml and .env with everything configured. The stack includes:
- Management server — API and web dashboard on port 443
- Signal server — WebSocket-based signaling for peer connections
- Coturn — TURN relay for peers that can't establish direct connections
- Zitadel — OpenID Connect identity provider for authentication
- Caddy — reverse proxy with automatic HTTPS
Start it:
docker compose up -d
Once it's running, open https://vpn.example.com in your browser. You'll see the NetBird dashboard where you can manage peers, create access policies, and monitor connections.
Want more networking guides? Get guides like this in your inbox — HomeLab Starter delivers one free deep-dive every week.
Adding Peers
On each machine you want to connect, install the NetBird agent and point it at your management server.
Linux (most homelab machines):
curl -fsSL https://pkgs.netbird.io/install.sh | sh
netbird up --management-url https://vpn.example.com
The first time you run netbird up, it opens a browser for SSO authentication. After you authenticate, the peer registers with your management server and gets a WireGuard IP from the 100.64.0.0/10 range.
Docker containers:
For services running in Docker, you can add NetBird as a sidecar:
services:
netbird:
image: netbirdio/netbird:latest
cap_add:
- NET_ADMIN
- SYS_RESOURCE
environment:
- NB_MANAGEMENT_URL=https://vpn.example.com
- NB_SETUP_KEY=your-setup-key-here
volumes:
- netbird-config:/etc/netbird
network_mode: host
Setup keys let you register peers without interactive SSO — useful for headless servers and containers. Generate them in the dashboard under Setup Keys.
Proxmox VMs and LXC containers:
Install the agent directly inside each VM or container. For LXC, you'll need to allow the tun device:
# On the Proxmox host, for container ID 100:
echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >> /etc/pve/lxc/100.conf
echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" >> /etc/pve/lxc/100.conf
pct restart 100
Then install NetBird inside the container normally.
Access Policies
One of NetBird's strongest features is its policy engine. By default, all peers can talk to each other. That's fine for a small homelab, but as you add devices you'll want segmentation.
Policies are managed in the web dashboard under Access Control. You define groups (like "servers", "workstations", "iot") and rules for which groups can communicate.
A practical homelab setup might look like:
- servers group: Proxmox hosts, NAS, database servers
- workstations group: laptops, desktops
- monitoring group: Grafana, Prometheus nodes
- Allow workstations → servers (full access)
- Allow monitoring → servers (port 9090, 9100 only)
- Deny everything else by default
This gives you microsegmentation without touching VLANs or firewall rules on individual machines.
DNS and Service Discovery
NetBird includes a built-in DNS that resolves peer names automatically. Once a peer named proxmox-01 joins the network, other peers can reach it at proxmox-01.netbird.cloud (or your custom domain if configured).
To set a custom DNS domain, edit the management server config:
{
"DNSSettings": {
"DisabledManagementGroups": [],
"Domain": "lab.internal"
}
}
Now peers resolve as proxmox-01.lab.internal. This is useful when you want a consistent naming scheme across your homelab that works regardless of which physical network a device is on.
NAT Traversal and Relay
NetBird handles NAT traversal automatically using STUN for hole-punching and TURN (Coturn) as a fallback relay. In practice, most connections between homelab machines end up being direct — the relay is mainly for devices behind strict corporate NATs.
You can check connection status with:
netbird status --detail
This shows each peer, whether the connection is direct or relayed, latency, and bytes transferred. If you see a lot of relayed connections between machines on the same LAN, check that UDP ports 49152-65535 aren't being blocked by your firewall.
Monitoring and Maintenance
The management server exposes metrics at /api/metrics in Prometheus format. Add it to your existing monitoring stack:
# prometheus.yml
scrape_configs:
- job_name: 'netbird'
static_configs:
- targets: ['vpn.example.com:443']
metrics_path: /api/metrics
scheme: https
For updates, the Docker Compose stack can be updated with:
docker compose pull
docker compose up -d
Peer agents update independently — netbird packages from the official repo include automatic updates, or you can pin versions and update manually.
When NetBird Makes Sense
NetBird fits best when you want full control over your mesh VPN infrastructure and you're already comfortable running Docker services. If you just need two machines connected and don't care about self-hosting the control plane, Tailscale with a free account is simpler.
But if you're running a homelab with more than a handful of devices across multiple locations, NetBird's combination of self-hosted control, access policies, and SSO integration is hard to beat. You get the zero-config mesh VPN experience without depending on anyone else's servers.
