MeshHold vs Tailscale, Headscale, NetBird & Nebula
Five mesh VPNs ordered by where the control plane lives — including the rows where a shared key loses to one.
Tailscale publishes a shelf of comparison pages, one per competitor. Unlike ownCloud's, they are not a single table — mostly prose, with a real matrix only on the Nebula page. So there is no canonical row set to answer here. The rows below are assembled from the criteria Tailscale uses across those pages (setup, connectivity, security, performance, administration), the matrix on its Nebula page, and NetBird's own comparison table — then extended with the axes none of them has reason to carry.
These five differ mostly in one thing, so the table is ordered by it: where the control plane lives. Tailscale runs it for you. Headscale is that same control plane reimplemented so you can run it. NetBird ships you the whole product, coordination server included, under AGPL. Nebula has no control plane at all — an offline certificate authority signs each host, and the lighthouses only help peers find each other. MeshHold has no control plane either, and gets there with a single shared key instead of a CA. Read down a column and you are reading one answer to who decides that this machine is a member.
The asymmetry worth stating before the table rather than discovering halfway down it. For the other four, the overlay network is the product. For MeshHold the overlay is one service of a storage daemon; it exists because the files needed a transport, and it inherited that transport's properties. So MeshHold has no server to run, pay for or trust, and it keeps working on networks that drop everything unfamiliar. It also has no SSO, no per-peer rules, and no way to revoke one laptop without re-keying the network. If your question is how 200 employees' access follows an AD group, the answer is in one of the other columns and this page will not talk you out of it.
They also coexist — MeshHold's default range is 10.0.0.0/8 and Tailscale's
is 100.64/10, so running both on one machine is a supported configuration, not
a workaround.
Cells marked ts are Tailscale's claim about a competitor and nb NetBird's, rather than something we verified. Where MeshHold has nothing, the cell says so.
| MeshHold | Tailscale | Headscale | NetBird | Nebula | |
|---|---|---|---|---|---|
| Product & licensing | |||||
| License | AGPL-3.0, all of it | BSD-3 clients; closed control plane | BSD-3 | BSD-3 client; AGPLv3 server | MIT |
| Who publishes it | Independent | Tailscale Inc. | Community; not Tailscale1 | NetBird (DE) | Slack → Defined Networking |
| Backing | One maintainer, no VC | VC-backed | Volunteers1 | VC-backed | VC-backed |
| Hosted option | Planned 2026 | ✓ the default | — by design | ✓ | ✓ Defined Networking |
| Cost to run it yourself | Free, no limits | n/a — SaaS only | Free | Free | Free |
| Cost of the hosted tier | Planned 2026 | Free ≤6 users; $8 / $18 per user·mo | n/a | Free ≤5 usersnb; from $5 | Per host |
| Where the control plane lives | |||||
| Server deciding membership | None — the key is it2 | Tailscale's | Yours | Yours, or theirs | None — offline CA3 |
| What you must operate | Nothing | Nothing | Server + DB + TLS domain4 | Compose + IdP + TLS domain | Offline CA + ≥1 lighthouse |
| Peer discovery | LAN mDNS + invited peers2 | Control plane | Your Headscale | Signal service | Lighthouses (discovery only) |
| Node identity | None — one shared key5 | Device key + IdP | Device key + IdP | Device key + IdP | Per-host cert with groups |
| A vendor sees your device graph | No — no vendor | Yes | No | SaaS yes, self-hosted no | No, unless managed |
| Runs with the coordinator down | n/a | Existing peers only | Existing peers only | Existing peers only | ✓ CA is offline anyway |
| Control-plane tamper protection | n/a2 | ✓ tailnet lock | —6 | — | n/a — you hold the CA |
| Access control & identity | |||||
| SSO / OpenID Connect | — | ✓ any IdP, Standard+ | ✓ OIDC registration | ✓ free tiernb | —ts |
| MFA on membership | — TOTP guards the UI only | ✓ via IdP | ✓ via IdP | ✓ via IdP | — |
| Per-peer rules | — all holders equal5 | ✓ ACL policy file | ✓ ACLs, grants, autogroups | ✓ groups & policies UI | ✓ host firewall, cert groups |
| Where rules are authored | Per node, locally | Centrally | Centrally | Centrally | Per node, in its config |
| Fresh network's default posture | Deny all | Allow all until you write ACLs | Allow all until you write ACLs | Default allow-all rule | Deny all — empty firewall |
| Revoke one device | — re-key the network5 | ✓ one click | ✓ one command | ✓ one click | Blocklist, pushed everywhere7 |
| Credential expiry | ✓ per key, in days | ✓ key expiry | ✓ key expiry | ✓ + periodic re-auth | ✓ cert lifetime |
| Device posture / EDR | — | ✓ MDM, EDR, XDR | —6 | ✓ posture + EDR | — |
| Connection audit log | Local per node only | ✓ flow logs, streaming | ✓ network flow logs | ✓ Datadog, S3, Firehose | Host logs only |
| Connectivity & transport | |||||
| Data-plane protocol | libp2p Noise + ChaCha208 | WireGuard | WireGuard (their clients) | WireGuard | Custom: Noise IK + AES-GCM |
| Kernel WireGuard fast path | — userspace | Userspacenb | Userspace | ✓ on Linuxnb | n/a — userspace |
| Direct P2P + hole punching | ✓ | ✓ | ✓ | ✓ | ✓ |
| Relay when direct fails | ✓ Relay v2, yours | ✓ DERP, theirs by default9 | ✓ embedded DERP, yours | ✓ TURN, yours if self-hosted | ✓ host relays, yours |
| Overlay IPv6 | — IPv4 only | ✓ | ✓ dual stack | ✓ dual stack | ✓ since v1.1010 |
| Caller's IP seen by the service | — loopback11 | ✓ | ✓ | ✓ | ✓ |
| Names & routing | |||||
| Address assignment | Derived from the key2 | Control plane | Your Headscale | Control plane | In the certificate |
| Name resolution | ✓ <node>.mesh | ✓ MagicDNS, split DNS | ✓ MagicDNS, split DNS | ✓ + match domains | A / TXT from a lighthouse |
| Subnet router (whole CIDR) | Per-device, not a CIDR12 | ✓ | ✓ + route filtering | ✓ + HA routes | ✓ unsafe_routes + ECMP |
| Exit node | ✓ | ✓ | ✓ | ✓ all plans | Hand-rolled: 0.0.0.0/0 + NAT |
| Chained multi-hop exits | ✓ relays can't decrypt | — | — | — | — |
| Per-destination exit choice | ✓ LPM + failover13 | One exit at a time | One exit at a time | ✓ via routes | ✓ per route |
| Split tunnel / keep-LAN-local | ✓ system + auto + custom | ✓ | ✓ | ✓ | ✓ inherent |
| Kill switch on exit failure | ✓ fail-closed toggle | Client-dependent | Client-dependent | Client-dependent | — |
| Fleet administration | |||||
| Official web UI | ✓ on every node | ✓ central | — CLI only4 | ✓ central | — config files |
| Mesh-wide view | ✓ graph + edges, geo map | Device list | — CLI only | Peer list | — |
| Per-node telemetry | ✓ version, uptime, disk, RTT | Version, last seen, OS | Via CLI | + country infonb | — |
| Peer-to-peer speed test | ✓ in-UI, with history | CLI ping / netcheck | CLI ping | — | — |
| One policy, fleet-wide | — view only, no push14 | ✓ | ✓ | ✓ | — you distribute it7 |
| Bulk enrolment | One key / QR | ✓ auth keys | ✓ pre-auth keys | ✓ setup keys | ✓ sign certs in bulk |
| Assumes config management | No | No | No | No | Yes — Ansible/Chef/Puppet7 |
| Public API | ✓ REST + SSE + MCP | ✓ | ✓ gRPC + CLI | ✓ | — |
| Stated scale ceiling | Household, lab5 | Enterprise | One small tailnet1 | Enterprise | Slack-scale |
| Sharing a port you already expose — on nobody's table | |||||
| Runs on 443 behind a real web server | ✓ REALITY gateway | — | — | — | — |
| Runs on 22 behind a real sshd | ✓ SSH gateway | — | — | — | — |
| Invisible to an unauthenticated scan | ✓ pre-auth gateway15 | TCP/443, but recognisable | Same, on your DERP | TURN over TCP | — UDP, unmistakable |
| Router-grade QoS on the tunnel | ✓ both directions16 | — | — | — | — |
| Ad / tracker DNS sinkhole | ✓ built in | — | — | — | — |
| Beyond the overlay — on nobody's table | |||||
TCP and UDP forwards (-L/-R) | ✓ both, either way | TCP via serve | TCP via serve | Ingress proxy | — |
| Publish a LAN service publicly | ✓ reverse forward + UPnP17 | ✓ Funnel, on *.ts.net | ✓ Funnel | ✓ | — |
| Device-to-device file send | ✓ | ✓ Taildrop | ✓ Taildrop, Taildrive | — | — |
| Encrypted file storage & sync | ✓ the actual product | — | — | — | — |
| Untrusted nodes holding ciphertext | ✓ | — | — | — | — |
| S3-compatible storage server | ✓ bucket = vault | — | — | — | — |
| Mount as a drive | ✓ WinFsp / FUSE / WebDAV | — | — | — | — |
| Encrypted chat & A/V calls | ✓ built in | — | — | — | — |
| Music / video library | ✓ | — | — | — | — |
| Photo gallery | ✓ grouped by capture date | — | — | — | — |
| USB device passthrough | ✓ | — | — | — | — |
| Platforms & packaging | |||||
| Windows / Linux / Android | ✓ + Android TV | ✓ | ✓ their clients | ✓ | ✓ |
| macOS / iOS | — nothing built18 | ✓ | ✓ | ✓ | ✓ |
| Routers / OpenWrt | ✓ | ✓ | ✓ | ✓ | ✓ |
| Packaging | deb, rpm, Docker, MSI, OpenWrt | Packages, Docker | Binary, deb, Docker | Packages, Docker, Helm | Packages, Docker, Homebrew |
| Server prerequisites | None — one static binary | None — SaaS | Server + DB + TLS domain | Compose + IdP + TLS domain | CA + a routable lighthouse |
Notes
- Headscale is an independent reimplementation of Tailscale's coordination server, driven by Tailscale's own clients. It is explicitly "not associated with Tailscale Inc.", though one active maintainer is employed there and contributes on work time, with review by the others. It states its own scope as a single tailnet "suitable for a personal use, or a small open-source organisation" — so the fleet rows above are its declared design limit, not an oversight.
- Membership is one shared symmetric key. Each member derives its own
10.x.x.xaddress deterministically from that key plus its node id, so there is no address-assignment protocol, no lighthouse, no CA ceremony and nothing to sign. Peers find each other over LAN mDNS and through peers they have already been invited to;bootstrap_peersseeds a brand-new node once and is not a service anyone operates. - Nebula and MeshHold are the two columns with no server deciding anything, and they arrive there differently — this is the most interesting comparison on the page. Nebula's authority is a certificate authority you generate and keep offline. It signs each host a certificate carrying that host's overlay address, its name, and its group memberships, and every node's firewall rules are written against those groups. The lighthouses only answer "where is this host right now"; they authorise nothing. MeshHold's authority is a single shared symmetric key that carries no per-node identity at all. Nebula's model is strictly the better one for access control, and it is the honest comparison to make: it proves you can have per-peer rules without a control plane, which is a thing MeshHold does not currently do. What MeshHold buys with the difference is that there is no CA to generate, protect, or re-run when a host joins — you paste a key.
- Headscale has no official web UI;
headscale-uiandheadplaneare third-party. Its maintainers also state they do not support or encourage running it behind a reverse proxy or in a container, which rules out the deployment shape most self-hosters reach for first. - This is the row that decides most evaluations, so it is worth being blunt about. A MeshHold mesh network is one shared secret. Everyone holding it is an equal member; the only access control is each node's own choice of which local ports it exposes, and that choice applies to every member identically. There is no "Alice's phone may reach the NAS but not the database". And revocation means rotating the key on every remaining member, because a shared credential cannot be withdrawn from one holder. For a household, a lab, or a handful of machines you personally own, that is a feature — nothing to run, nothing to log into, no IdP, no CA. For a company where people join and leave, it is disqualifying, and no amount of the rest of this table compensates. All four other columns exist because that problem is hard, and all four solve it.
- Headscale's docs enumerate what it supports rather than what it does not. Cells reading "—" for Headscale are features absent from that list — device posture, MDM/EDR integrations, SCIM, tailnet lock — not features it documents as unsupported. The one limitation it names explicitly is that OIDC groups cannot be used in ACLs.
- Nebula revokes through
pki.blocklist, a list of certificate fingerprints — and it is explicitly not distributed by the lighthouses. You push it to every host yourself, which is why Nebula in practice assumes Ansible, Chef or Puppet. So both no-control-plane columns pay for revocation by touching every node; Nebula pays less (append a fingerprint) than MeshHold (a new key everywhere), and short certificate lifetimes soften it further. - Not WireGuard. MeshHold's overlay rides the same libp2p transport as its file replication — Noise handshake, ChaCha20-Poly1305 AEAD end-to-end between entry and exit, yamux multiplexing. That is why it inherits the port-sharing transports and the multi-hop chaining, and also why it does not get kernel WireGuard's throughput.
- Tailscale lets you run your own DERP relays; the row is about the default, which is that relayed traffic transits Tailscale's infrastructure. It is encrypted end-to-end in every case.
- IPv6 overlay addresses landed in Nebula v1.10 (December 2025) together with a new v2 certificate format; v1 certificates carry a single IPv4 address.
- The overlay is userspace, and the destination service sees a loopback source address rather than the caller's mesh IP. Fine for anything that authenticates by credential; wrong for anything that authorises by source IP. Tailscale's userspace mode has the same property.
- MeshHold fronts individual LAN devices — a printer, a camera, a switch's web
UI — each getting its own virtual mesh IP and
.meshname. It does not advertise a CIDR the way a Tailscale subnet router or a Nebulaunsafe_routesentry does. For a handful of named devices this is easier; for "everything on 192.168.1.0/24", it isn't. - Exits are longest-prefix-match rules with priorities: two
0.0.0.0/0rules at different priorities form a hot-standby pair, a/32above a/8carves out an exception, and the daemon fails over down the chain to the next live exit. See The Private Mesh VPN. - Every node's web UI shows the whole mesh, not just itself. The Network page draws the live peer graph including the edges between other nodes, a geographic view, and per-node telemetry — software version, uptime, used and free block storage, measured round-trip time, link transport, mesh addresses and open ports — all of it carried by the topology gossip beat rather than fetched from a server, so any node is a viewing station for the network. What you cannot do from there is change another node: its policy, its open ports and its exits are that node's own local decisions. MeshHold therefore has fleet observability without fleet administration — the opposite trade to Nebula, which pushes one policy everywhere through your config-management tool and offers no view at all.
- The port-sharing transports are the one axis where MeshHold is not
competing with these four but with a different category. REALITY sits on
443in front of a real web server and the SSH transport sits on22in front of a real sshd; in both cases authentication happens before the mesh service is reachable, so a scan of the host finds nginx or OpenSSH and no trace of a node. That also means no second port is exposed, and that the link is shaped like ordinary HTTPS or SSH — which is what keeps it working where only recognised protocols pass. All four alternatives want an inbound port of their own and answer on it: WireGuard's handshake is trivially fingerprinted and Nebula's is a bare UDP protocol of its own. - Classifies and shapes traffic on the uplink before it enters the tunnel, and instructs the exit to pace the downlink — so a bulk transfer stops starving DNS and VoIP. This is a home-router feature that no mesh VPN in this table offers.
- A reverse forward publishes a local service through any peer with a public
address — your own VPS, on your own domain, over TCP or UDP. Tailscale
Funnel is easier and needs no VPS, but terminates on
*.ts.netand is HTTP/TCP only. - Stronger than "no app": there is no macOS build at all — not a client,
not an exit, not a headless daemon. The tree carries
darwinbuild-tagged files for the tray, keystore and autostart, so the source would compile, but no build script targets it and the updater has no macOS artifacts to offer. There is no iOS app either. All four of the other columns ship both.
If you need Layer 2
Every column above is an L3 overlay: it carries IP, and broadcast, multicast and mDNS do not cross it. If what you need is one Ethernet segment — LAN game discovery, service auto-discovery across sites, industrial protocols that assume their peers are on the same wire — none of these five does it and ZeroTier is where to look, because its overlay is L2 by design.
Check the licence before you plan a self-hosted deployment around it. ZeroTier's
agent is MPL-2.0, but its network controller lives under nonfree/ in the same
repository with a source-available licence permitting non-commercial use
only — personal, academic, or a 30-day evaluation. Running a controller "in a
production, staging, or development environment for business purposes" requires
a paid licence.
Which one to pick
Tailscale if you want it working in five minutes and staying that way, and a SaaS control plane holding your device graph is acceptable. The largest free tier here, the best-documented policy model, the fewest moving parts.
Headscale if that last clause is the whole objection. You keep Tailscale's clients and its feature surface — ACLs, MagicDNS, Funnel, Taildrop, flow logs — and move the brain onto your own box. Go in knowing it is not Tailscale's product, it scopes itself at one small tailnet, and there is no official UI.
NetBird if "self-hosted" has to mean the whole product, from a vendor that supports it. The only column here where the coordination server is AGPL and self-hosting is a first-class deployment, with SSO and HA routes in the free tier that Tailscale charges for. You will run Compose, an IdP and a TLS domain.
Nebula if you want no control plane at all and still want real per-peer rules — the Slack-scale answer, and the most rigorous design in the table. The price is a PKI you own for life and a config-management tool to push it.
MeshHold if the server is the part you object to and a shared key is enough authority for the machines involved, or if your network filters everything it does not recognise — or, most often, if what you actually wanted was encrypted storage across your own machines, and would rather the overlay, the exits, the S3 endpoint and the chat came out of one daemon than four subscriptions. Its mesh is a household and homelab tool, not a fleet-management product, and the table above should make clear which parts of that are choices and which are limits.
For the overlay itself, start with The Flat Mesh LAN and The Private Mesh VPN. For what the overlay is carrying, see Core Concepts.