Skip to content
Go back

Mesh VPN Showdown: Tailscale, Nebula, ZeroTier, NetBird

By SumGuy 12 min read
Mesh VPN Showdown: Tailscale, Nebula, ZeroTier, NetBird

Your WireGuard Config Has 47 Peers and You’re Having a Bad Time

You know the drill. New device joins the homelab, you update 47 [Peer] blocks across 47 config files, restart the daemon on half of them, pray the NAT traversal works, and it’s 2 AM by the time the Proxmox node can actually talk to the Pi. Congratulations: you’ve reinvented pain.

Mesh VPNs solve this. Instead of you being the router, every node talks to every other node directly — or through a relay when NAT gets stubborn. The control plane handles key distribution. You handle snacks.

The problem is there are now four serious contenders in this space, each with a very different philosophy: Tailscale (magic UX, SaaS control plane), Nebula (Slack-built, fully self-hosted, certificate-based), ZeroTier (the veteran, Layer-2 capable, complicated licensing history), and NetBird (newer kid, open-source WireGuard mesh with SSO). They’re not interchangeable. Picking the wrong one for your use case means either regretting the vendor lock-in or spending a weekend migrating off a self-hosted nightmare you didn’t need.

Let’s go through them honestly.


Tailscale: The One That Just Works (For a Price)

Tailscale is built on WireGuard but abstracts every hard part away. You install a client, log in with Google/GitHub/your SSO provider, and your device appears on the tailnet. Full stop. No key exchange, no firewall rules, no DNS headaches — it handles all of it.

How It Connects

Tailscale’s control plane is hosted at login.tailscale.com. It handles key distribution and DERP (relay) servers. Direct connections happen via STUN/ICE-like NAT traversal using a protocol called “disco.” If direct connection fails — because you’re behind CGNAT or a corporate firewall that hates you — it falls back to Tailscale’s DERP relay network. You don’t notice either way. That’s the point.

ACLs and Identity

ACLs are defined in HuJSON (JSON with comments — civilized) in the admin console. You can write rules like “tag:prod can reach tag:db on port 5432” and it syncs across every device. ACLs are enforced at the kernel level, not iptables spaghetti.

Identity is tied to your SSO provider. Every device gets a certificate signed by Tailscale’s coordination server. This is great until it isn’t — if Tailscale’s control plane is down, existing connections survive but nothing new comes up.

2026 Pricing Reality Check

Tailscale’s free tier is 6 users, unlimited devices (updated April 2026). That’s genuinely usable for a homelab. The Personal plan ($0 for solo use) and Standard ($8/user/month) are fine for small shops. The catch: anything enterprise-y — SSO with custom SAML, audit logs, policy enforcement — pushes you into pricing conversations.

Self-Hosting the Control Plane: Headscale

If the SaaS dependency bothers you, Headscale is the open-source Tailscale-compatible control plane you run yourself. It’s solid and actively maintained — I’ve written about Headscale separately (check the self-hosting section), so I won’t repeat that whole setup here. Short version: swap login.tailscale.com for your Headscale server, keep the same clients, regain control.

Who It’s For

Solo homelabbers who want zero friction. Small teams that trust cloud-hosted coordination. Anyone who values UX over self-hosted purity.

Terminal window
# Install and join a tailnet in under 60 seconds
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up --login-server https://your-headscale.example.com # or omit for SaaS

Nebula: The Paranoid Engineer’s Choice

Nebula was built by Slack’s infrastructure team for internal use and open-sourced in 2019. It’s fully self-hosted, certificate-based, and has no SaaS dependency at all. There is no company hosting your control plane. There is no free tier. There’s just you and a binary.

The Lighthouse Model

Nebula doesn’t have a central control plane in the traditional sense. Instead, you designate one or more “lighthouse” nodes — regular Nebula nodes that also track IP-to-address mappings. When a node comes online, it registers with the lighthouse. When it wants to reach another node, it asks the lighthouse for the address and then opens a direct P2P connection.

The lighthouse needs a stable public IP or hostname. It’s not a relay — traffic doesn’t flow through it unless you explicitly configure it as one. It just answers “where is node X?” questions.

lighthouse.yml
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/lighthouse.crt
key: /etc/nebula/lighthouse.key
static_host_map:
"10.42.0.1": ["lighthouse.example.com:4242"]
lighthouse:
am_lighthouse: true
listen:
host: 0.0.0.0
port: 4242
firewall:
outbound:
- port: any
proto: any
host: any
inbound:
- port: any
proto: icmp
host: any
client-node.yml
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/node.crt
key: /etc/nebula/node.key
static_host_map:
"10.42.0.1": ["lighthouse.example.com:4242"]
lighthouse:
hosts:
- "10.42.0.1"
listen:
host: 0.0.0.0
port: 0
firewall:
outbound:
- port: any
proto: any
host: any
inbound:
- port: 22
proto: tcp
host: any

Certificate-Based Identity

This is where Nebula earns its stripes for paranoid ops. Every node gets a certificate signed by your CA, with an embedded Nebula IP and optional groups. ACLs in the config reference those groups: “nodes in group servers can reach databases on port 5432.” The trust anchor is your CA key — you control it completely.

Rotating the CA means re-issuing all certs. That’s a pain, but it’s your pain, not a vendor’s incident.

The Trade-Off

Nebula’s UX is rough compared to Tailscale. Mobile clients exist (iOS/Android) but configuration is manual — you’re copying a cert and config YAML to your phone. There’s no admin GUI, no SSO integration out of the box, no “magic” device registration. Everything is intentional and manual.

NAT traversal is good but not magic. Nebula does UDP hole-punching. It handles most consumer NAT scenarios fine. CGNAT and corporate outbound-only firewalls are trickier — you may need a relay configured.

Who It’s For

Regulated environments. Anyone who cannot accept a SaaS control plane. Multi-site homelabs where you want air-gapped cert management. The person who said “I trust myself more than I trust anyone’s cloud.”


ZeroTier: The Old Guard With Baggage

ZeroTier has been around since 2013. It was doing mesh networking before it was cool, and it shows — both the good parts and the accumulated technical debt.

Layer-2 Is Actually Useful

ZeroTier’s party trick is operating at Layer 2. You can bridge ethernet segments across the internet. This means broadcast traffic, ARP, DHCP, Spanning Tree — all the stuff that normally doesn’t cross network boundaries. For some use cases (Wake-on-LAN across sites, legacy apps that rely on broadcast discovery, Minecraft LAN parties across the internet) this is genuinely great.

For most things you probably don’t need it, and Layer-2 semantics over WAN come with storm risks if you misconfigure bridging. But it’s there.

How It Works

ZeroTier has “roots” (their public coordination network) and “moons” (your self-hosted coordination node). By default you’re using ZeroTier’s roots. You can run your own moon and route around their infrastructure, but nodes still have the concept of their default root path baked in.

Networks are identified by a 16-hex-digit ID. Join a network, approve the device in the controller, you’re on. The controller can be self-hosted via ztncui or ZeroTier’s own Central dashboard (SaaS).

Terminal window
# Install ZeroTier
curl -s https://install.zerotier.com | sudo bash
# Join a network
sudo zerotier-cli join <network-id>
# Check status
sudo zerotier-cli status
sudo zerotier-cli listpeers

The License and Governance Situation

Here’s the uncomfortable bit. ZeroTier went through a rough patch with licensing changes and unclear governance around 2023–2024. The core client is BSL (Business Source License) which converts to Apache after 4 years — not truly open-source. There was community frustration. There are forks.

For personal use none of this bites you. For anything production or commercial, read the license before you depend on it. The free tier (25 devices) is generous. Business plans are reasonable. But the vibe is different from a fully open-source project.

Who It’s For

Legacy network applications needing Layer-2. Anyone who needs that broadcast/ARP behavior. People who want a self-hosted option but don’t want to deal with certificate management. Users comfortable with the licensing trade-off.


NetBird: The New Hotness With WireGuard Underneath

NetBird is the newest serious contender here (2021, open-sourced 2022). It’s fully WireGuard-based, fully open-source (Apache 2.0), and the entire control plane — management server, signal server, relay — can be self-hosted. It also ships with real SSO integration out of the box.

Architecture

NetBird splits the coordination into two services: the Management server (handles network topology, peer distribution, ACLs) and the Signal server (helps peers find each other for direct connection). There’s also a Relay (based on the TURN protocol) for when direct connection fails.

All three are distributed as containers. The self-hosted deployment is a docker-compose.yml away from working.

Terminal window
# Self-hosted NetBird server (from netbird.io/selfhosted)
wget https://raw.githubusercontent.com/netbirdio/netbird/main/infrastructure_files/getting-started-with-zitadel.sh
chmod +x getting-started-with-zitadel.sh
./getting-started-with-zitadel.sh

This gives you a management server + Zitadel (an open-source identity provider) pre-wired together. SSO works from day one — you get proper OIDC/OAuth2 flows, user management, device approval. For a self-hosted option, the UX is surprisingly close to Tailscale.

ACLs and Groups

NetBird’s ACL model uses peers and groups. You define network policies like “group servers allows inbound 22/tcp from group admins.” Policy is enforced at the peer level using iptables rules generated by the agent. Changes propagate in seconds.

The client is available for Linux, macOS, Windows, iOS, Android, and Docker. CLI and GUI both exist.

Where It’s Still Maturing

NetBird is newer and the rough edges show in places — documentation has gaps, some edge cases in the management UI aren’t smooth, and the Zitadel dependency for self-hosted SSO adds operational complexity. If you just want quick-and-dirty without SSO, there’s a simpler setup, but then you lose some of the identity features.

Stability has been good in practice, but the project moves fast. Watch the changelog.

Who It’s For

Teams that want self-hosted control but won’t accept “configure your certs manually.” Anyone who wants Tailscale-like UX on their own infrastructure. Projects where Apache 2.0 licensing matters.


NAT Traversal: Where the Real World Bites

Here’s the honest reality across all four:

ScenarioTailscaleNebulaZeroTierNetBird
Typical home NATDirect (disco)UDP hole-punchDirectDirect
CGNATDERP relayNeeds relay nodeUses roots/relayTURN relay
Corporate outbound-onlyDERP relayHardHarderTURN relay
Mobile (LTE)ExcellentWorkableGoodGood

Tailscale and NetBird handle CGNAT gracefully because they have cloud-based (or self-hosted) TURN/DERP infrastructure. Nebula is the most transparent about what’s happening but needs you to plan the relay topology yourself. ZeroTier’s roots handle relay but you’re dependent on their infrastructure for it unless you’ve set up moons properly.


Mobile Clients


Decision Matrix

TailscaleNebulaZeroTierNetBird
Control planeSaaS (or Headscale)You own itSaaS (or Moon)Self-hosted
ProtocolWireGuardNoise protocolCustom (not WG)WireGuard
Identity modelSSO/OAuth2Certificate CAController authSSO/OIDC
ACLsHuJSON, powerfulYAML, powerfulNetwork controllerPolicy engine
Layer 2NoNoYesNo
Mobile UXExcellentRoughGoodGood
Free tier6 users, unlimited devicesSelf-hosted25 devicesSelf-hosted
LicenseProprietary + Headscale (OSS)MITBSLApache 2.0
Setup frictionMinimalHighMediumMedium-High
NAT/CGNATExcellent (DERP)Manual relayGoodGood (TURN)

Recommendations by Use Case

Solo homelab, just want it to work: Tailscale on the free tier. Use Headscale if the SaaS dependency bothers you. You’ll be done in 20 minutes and your Proxmox cluster will actually talk to your Pi. Your 2 AM self will thank you.

Small team (5–20 people), regulated industry, no SaaS: NetBird self-hosted. You get SSO, proper ACLs, WireGuard performance, and you own the control plane. Budget a day for the initial Zitadel setup.

Paranoid infrastructure, air-gapped sites, certificate-based trust: Nebula. There is no phone-home, no SaaS, no surprise license change. You own the CA, you control everything. Accept that you’ll spend time on configuration and relay planning.

Legacy apps needing Layer-2, LAN simulation, broadcast: ZeroTier. It’s the only one in this list that does Layer-2. Just read the license and watch the project governance before committing production workloads.

IoT fleet (many devices, low admin overhead): Tailscale with device tags and ACLs, or Nebula if you want cert-pinned device identity and offline operation. NetBird’s management server adds overhead that might not be worth it for 200 Raspberry Pis that just need to phone home.


The Honest Bottom Line

There’s no universally correct answer, which is annoying but true. Tailscale wins on UX by a mile — if you’ve never used it, the first time a new device “just appears” on your network without touching a config file is borderline offensive. But that UX lives on someone else’s servers.

Nebula is what you reach for when you need to explain your architecture to a security auditor and “the control plane is on a vendor’s SaaS” is not an acceptable sentence. It’s the boring, correct answer for regulated environments.

NetBird is narrowing the self-hosted UX gap fast. If you’re evaluating today and you care about open-source + self-hosting + not hating your life, give it serious consideration. It wasn’t ready two years ago. It mostly is now.

ZeroTier deserves a slot specifically because nobody else does Layer-2. That’s a niche use case, but when you need it, you need it.

Pick the one that matches your threat model and your patience for configuration. They’ll all get your nodes talking to each other. The question is whether you’re talking to yourself at 2 AM because DNS isn’t resolving, or whether that was someone else’s problem.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Next Post
Dify: Visual Agent Workflows

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts