The problem: managing ten manual WireGuard tunnels
WireGuard is excellent — fast, modern, cryptographically solid. But its configuration model is static: each peer must know the public IP and public key of all its peers. In a fleet of ten clients with nomadic workstations, offices behind CGNAT, and VPS with variable IPs, you spend more time synchronizing wg0.conf files than doing productive work. Add a VPS, modify the peer list on nine machines. Remove a technician, revoke their key everywhere. A subnet changes? Start over. This is the operational nightmare that NetBird was designed to eliminate.
- Automatic mesh: NetBird manages the control plane — every new peer announces itself, others discover it without manual intervention.
- NAT and CGNAT traversal: NetBird uses STUN to establish direct peer-to-peer connections through residential and corporate NATs.
- Automatic TURN relay: when direct connection is impossible (strict firewall, double NAT), NetBird silently switches to an encrypted relay.
- Granular access audit: access control policies define which peers can reach which services — visible from the dashboard.
- Open source (BSD-3 for the client, AGPLv3 for the control plane): no vendor lock-in, self-hosting possible.
Prerequisites
Before installing NetBird, verify that your infrastructure meets the following requirements.
- A ServOrbit VPS running Ubuntu 22.04/24.04 or Debian 12, with root access.
- A NetBird Cloud account (free for up to 5 peers) or an already-deployed self-hosted control plane.
- Outbound ports 443 (HTTPS/WSS) and 3478 (STUN/UDP) not blocked from the VPS.
- The Peer Expose feature enabled on your account (available on Team and higher plans, or on a self-hosted control plane).
Connect a ServOrbit VPS to a NetBird network
Here is the complete procedure for connecting a ServOrbit VPS to your NetBird mesh network.
Install the NetBird agent
On the VPS, add the official repository and install the package:
curl -fsSL https://pkgs.netbird.io/install.sh | sh
Verify the installed version:netbird versionshould display0.76.x.Generate a setup key
In the NetBird dashboard (app.netbird.io or your self-hosted instance), go to Setup Keys and create a reusable or one-time key. Copy it — it only appears once.
Connect the peer to the control plane
On the VPS:
netbird up --setup-key <YOUR_SETUP_KEY>
For a self-hosted control plane, add--management-url https://netbird.your-domain.com:443. The command returns immediately; the peer appears in the dashboard within seconds.Add the peer to a network group
In the NetBird interface, navigate to Peers, select the new VPS and add it to the desired group (e.g.
agency-clients). Access policies linked to this group apply immediately — no restart needed.Verify mesh connectivity
From another peer already in the network:
netbird statusthenping 100.x.x.x
A responding ping confirms the tunnel is established.
`netbird expose`: an internal service without a public port
The netbird expose command, available since version 0.66 and consolidated in the 0.76 branch, lets you make a service listening locally (on 127.0.0.1 or a private network) accessible from the Internet via NetBird's reverse proxy — without opening a single port on the VPS firewall. The created service is ephemeral: it automatically disappears when the command stops.
Example: your monitoring panel (Grafana, Netdata) listens on localhost:3000 and should only be accessible to authorized mesh members:netbird expose --protocol http --local-address localhost:3000 --with-user-groups supervision-admins
NetBird generates a public URL at *.tunnel.netbird.io. Port 3000 on the VPS remains closed at the firewall level.
For password-protected access without SSO, add --with-password: NetBird displays a random password you share with your collaborators. Useful for emergency access to a client without an account in your NetBird tenant.
Agency use case: connecting client VPS, office, and admin workstation
Recommended NetBird topology for an agency managing ten independent clients: Create one group per client (e.g. client-acme, client-contoso). Each client's VPS is a member of its client group. Admin workstations are members of their respective client group only. An access policy links each group to itself. The agency office is in an agency-ops group with access to all client groups — the only cross-cutting peer. SSH to client VPS uses the mesh IP (100.x.x.x); no public SSH port is needed:ufw allow in on netbird0 to any port 22 then ufw deny 22
Scroll the table
| Criterion | NetBird 0.76 | Tailscale | Manual WireGuard |
|---|---|---|---|
| Peer management | Automatic (centralized control plane) | Automatic (Tailscale cloud) | Manual (wg0.conf files on each node) |
| NAT/CGNAT traversal | Automatic STUN + TURN | Automatic STUN + DERP | Requires public IP or port-forward |
| Pricing model | Free up to 5 peers; Team/Business plans; self-hosted free | Free up to 3 users; paid plans for teams | Free (software), operational cost in time |
| Open source | Yes (BSD-3 client, AGPLv3 server) | Client open source (BSD-3), proprietary server | Yes (GPLv2 kernel, MIT userland) |
| Expose service without open port | Yes (`netbird expose`) | No (Funnel available but different) | Not native (manual SSH tunnel) |
| Audit and access policies | Full web interface, groups and policies | ACL via HuJSON file, web interface | None — only AllowedIPs per peer |
Troubleshooting: 3 common problems
1. Unreachable peer (Status: Disconnected) — Run netbird status --detail to see the ICE state. If you see no candidate pairs, the issue is network: verify outbound UDP port 3478 is open. If direct connection fails but TURN is available, NetBird switches automatically.
2. STUN/TURN blocked by corporate firewall — NetBird supports TURN over TCP/443. Configure in the dashboard: Settings → Relay → Force TCP.
3. Reading logs — On Linux with systemd:journalctl -u netbird -f --since '5 minutes ago'
Key messages to watch: failed to connect, signal disconnected, peer connected via relay.
Troubleshooting: the NetBird proxy stays on "Issuing certificate…"
Since NetBird started offering its self-hosted reverse proxy, one symptom keeps coming back in the issue tracker: the service created in the dashboard sits on "Issuing certificate…" indefinitely and is never reachable. NetBird issue #5517, opened on 5 March 2026 and still open at its last activity on 19 October 2026, has 35 comments. The proxy log most often shows this message: acme/autocert: unable to satisfy "https://acme-v02.api.letsencrypt.org/acme/authz/…" for domain "subdomain.site.tld": no viable challenge type found. It says the certificate authority received no valid answer to its challenges; it does not say why. There is therefore no single cause: participants describe several, and only one is confirmed by the NetBird team. Here is a diagnostic order that rules causes out one at a time.
Read the proxy log
Run
docker compose logs proxy | grep -i acme: the NetBird documentation points to this command for services stuck incertificate_pendingor moved tocertificate_failed. Note the exact error text before changing anything, becausepermission deniedandno viable challenge type founddo not have the same remedy.Check permissions on the certificates folder
An error such as
open /certs/acme_account+key…: permission deniedis the only case settled by a repository collaborator, who answers that no update will fix it and that permissions are at fault. One participant reports fixing it by giving thecertsfolder to user 1000:1000 (chown 1000:1000) and mounting an empty folder on/var/lib/netbird. That is a reported fix for their own setup: check which user your container runs as before copying it.Verify DNS, CAA records and ports
The name must resolve to the proxy address and no CAA record may exclude the authority in use. Port 443 must be reachable from the Internet for the
tls-alpn-01challenge, which is the default; port 80 must be too forhttp-01. The documentation states that Let's Encrypt validates from several locations around the world, so upstream geographic filtering can make validation fail.Rule out a CDN that does not relay the challenge
The documentation warns that a service placed in front of the proxy, Cloudflare for example, may not pass the
acme-tls/1ALPN protocol. In that case switch toNB_PROXY_ACME_CHALLENGE_TYPE=http-01. These checks rule causes out without guaranteeing success: one participant verified DNS, Cloudflare in DNS-only mode, ports 80 and 443 open and no CAA record, then got the same error with both challenge types.Examine the Traefik in front
If Traefik relays TLS to the proxy through a TCP router with
tls.passthrough=true, check that the HTTPS entry point carriesallowACMEByPass=true. The note that follows explains what this option does and what it does not prove.
- Confirmed by the team — a
permission deniederror on the/certsfolder comes from file system permissions, not from the proxy version; thefailed to get active profile statewarning about the embedded client's profile is unrelated to the proxy and not critical, and its message is to be fixed in a future release. - Reported by several participants — adding
allowACMEByPass=trueto Traefik's HTTPS entry point unblocks issuance. Several confirm it, but two others say the option was already set on their side and the blockage persists, one of them on proxy version 0.74.4. - Reported by a single participant, unverified — on NetBird Cloud, slow issuance on the ZeroSSL side, combined with a 5-minute timeout in Go's autocert library, would explain the failures. The author states they are reasoning from the outside, without confirmation from the team.
- Not established — no single cause to date: the issue still carries the
triage-neededlabel as read on 31 October 2026. Do not present any of these leads as the cause of your case before you have tested it.
The getting-started.sh script in the NetBird repository sets --entrypoints.websecure.allowACMEByPass=true on Traefik. According to Traefik's documentation, this option, disabled by default, has your own routers handle ACME TLS and HTTP challenges instead of the internal ACME router, and lets the TLS-ALPN challenge through to a TLS router that you define. Use the name of your own entry point (websecure, https…): one participant had to set it on both the HTTP and the HTTPS entry points. It does not replace reading the log.
Closed origin: getting the certificate through DNS-01 with lego
As long as the certificate depends on a tls-alpn-01 or http-01 challenge, the authority must reach your proxy from the Internet. That conflicts with an origin closed to a CDN's ranges only, with an upstream firewall you do not manage, or with geographic filtering. The dns-01 challenge removes that dependency: it proves control of the domain with a temporary TXT record created through the DNS provider's API. As of 31 October 2026 the NetBird proxy does not include it natively: the request, NetBird issue #5450, opened on 25 February 2026 with 30 comments, is still open. The NetBird documentation does describe a route, "private proxy with lego": lego obtains and renews a wildcard certificate through DNS-01, a deploy hook copies it into a shared volume, and the proxy loads it and hot-reloads it after each renewal. A participant in the issue says they set it up without difficulty and that it can also serve public services.
- Proxy variables —
NB_PROXY_WILDCARD_CERT_DIRpoints to the wildcard certificate folder andNB_PROXY_PRIVATE="true"enables private mode. Pin the image version: it must support both variables. - Private mode closes nothing on its own —
NB_PROXY_PRIVATEdoes not disable the public listener. Remove the public ports and the ingress routes to the proxy yourself. - Wildcard scope — it covers only one subdomain level. A name outside its coverage falls back to the built-in ACME, which cannot succeed if the proxy is fully private.
- Certificate exposure — public authorities record the wildcard and the base domain in Certificate Transparency logs, and a compromised wildcard key affects every name it covers.
- Operations — use the production ACME server, since test certificates are not trusted; back up the lego and certificate volumes; plan for a single issuer or a secure distribution of the certificate pair for a cluster of several hosts.
Access control policy: in Access Control → Policies, create a rule that only allows the agency-ops group to reach port 22 on client groups. Other ports (80, 443) can be accessible to the client group itself. This granularity prevents a compromised workstation in the mesh from pivoting to all client VPS.
Conclusion: fewer firewall rules, more real security
NetBird 0.76 represents a paradigm shift for managing a distributed VPS fleet. Instead of multiplying UFW rules and static WireGuard keys, you define groups and policies once — and the control plane handles the rest. The netbird expose command goes further: it physically removes services from Internet exposure without reconfiguring the firewall. For an agency managing ten clients or a company with distributed offices, this is the highest-impact attack surface reduction per hour invested.