NetBird Part 2 - Standing Up Your Own Control Plane
NetBird Part 2 - Standing Up Your Own Control Plane
The first post in this series made the case for NetBird: a
WireGuard-based mesh where your machines find each other peer-to-peer,
coordinated by a control plane you can run yourself. This post is about
that control plane. Not a line-by-line install, the docs do that and
they change, but the thing worth understanding before you run any
script: what you are actually deploying, which decisions matter, and
where the sharp edges are.
If you skipped part one, the one-sentence recap: NetBird splits into a
control plane that decides who may talk to whom and a data plane that
is your actual traffic going directly between peers. Self-hosting means
you run the control plane. Here is what that control plane is made of.
The Components You Are Running
A self-hosted NetBird control plane is a handful of services, and it is
worth knowing what each one does, because when something breaks it is
always one specific component and knowing which saves you hours.
The management service is the brain. It holds the network state: which
peers exist, what addresses they have, which groups they are in, and
what the access policies say. Every agent checks in with it, and every
change you make in the dashboard lands here. This is the component that
matters most, because it holds your entire network's membership and
rules.
The signal service is the introducer. When two peers want a direct
connection, signal relays the small negotiation messages that let them
find each other and agree on how to connect. It sees the handshake, not
the traffic. Once two peers are introduced, signal is out of the
picture.
The relay, backed by a STUN/TURN server (Coturn), is the fallback.
Most peer connections end up direct, but when two peers are both behind
NAT that refuses to cooperate, the relay carries their encrypted
traffic between them. It never sees plaintext, WireGuard is still doing
the encryption end to end, it just forwards the ciphertext when a
direct path cannot be built. This is the component people most often
misconfigure, because it needs its own ports and TLS handling and it
does not go through the reverse proxy the same way the rest does.
The dashboard is the web UI where you manage peers, groups, policies,
and keys. It talks to the management API.
And an identity provider handles who is allowed to log in and manage
the network at all. This is the piece that changed most recently, and
it is worth its own section.
The IdP Situation Got Simpler
If you looked at NetBird self-hosting a year ago and bounced off it,
this is why: it used to require you to stand up Zitadel, a full
open-source identity platform, alongside NetBird, just to have
somewhere for users to log in. That is a second complex system to
deploy, back up, and maintain, and for a homelab it was a lot of
machinery to get a mesh running.
As of 2026 that is no longer the default. NetBird now ships an embedded
identity provider and local user management. The current quickstart is
a single netbird-server container configured with a config.yaml, with
users created and managed directly in the dashboard, no external IdP
required at all. For a homelab or a small team, this is the path: far
less to run, far less to break.
The external-IdP route still exists and is now the advanced path. You
reach for it when you already run an identity provider, Zitadel,
Keycloak, Authentik, Google, Entra, and want NetBird logins to go
through it so that access is governed in one place and offboarding
someone from your IdP also removes their NetBird access. That is a real
benefit at team scale and pure overhead for a solo homelab. The 2026
change is that you now choose it deliberately when you need it, instead
of being forced into it to get started. If you read an older guide
built around standalone Zitadel and separate management, signal, and
relay containers wired through management.json, you are looking at the
advanced architecture; the new combined setup is simpler.
What You Actually Need to Provide
The control plane wants a few things from you, and they are the usual
things any self-hosted service with a web UI and TLS needs.
A public server. The control plane has to be reachable by every peer,
including peers out on the internet, so it lives on a VM with a public
address, at any of the usual providers. It does not need to be large;
the management service is light and the traffic that matters never
touches it.
A domain name and TLS. Peers and the dashboard talk to the control
plane over HTTPS, so you need a hostname pointing at the server and a
certificate. NetBird's setup uses Caddy as the reverse proxy, which
handles automatic certificates, so this is mostly a matter of pointing
DNS at the box.
The relay ports open. This is the one that catches people. The relay
and TURN service need their specific ports reachable, and they do not
sit behind the reverse proxy the way the dashboard and API do. Most
self-hosting failures I have seen reports of are relay connection
errors, peers reach the API and signal fine but relay fails, and it is
almost always a port or a TLS-termination mismatch on the relay path.
When you debug a self-hosted NetBird, assume the relay first.
Peers Join With Setup Keys
Once the control plane is up, machines join it, and the mechanism worth
knowing from the start is the setup key. A setup key is a
pre-authorized token that lets a machine enroll into your network
without a human doing a browser login on that machine. You generate it
in the dashboard, and it is how you enroll headless servers,
containers, and anything without a browser.
This matters for the kind of infrastructure most of us run. A server in
a datacenter does not have someone sitting at it to click through an
SSO flow. You give it a setup key, the agent uses it to register with
your management service, and the machine appears in your network. Keys
can be reusable or single-use, and can be scoped so anything enrolling
with a given key lands in a specific group with specific access. That
last property is the bridge to the next post, because groups and
policies are how the flat mesh becomes an actually governed network.
The Sovereignty Point
It is worth restating why you are doing this instead of clicking the
managed cloud option, which genuinely does work in a few minutes.
The control plane holds the map of your entire private network and the
policy over it. Who exists, who can reach what, which machine is where.
Running it yourself means that map lives on your server, under your
control, governed by your rules, with no third party holding the
authority over your network's structure. The peer keys never leave your
machines regardless, WireGuard generates them locally and only public
keys are ever shared, but the membership and the policy are the
sensitive part, and self-hosting keeps them yours.
For a homelab, or for anyone who takes owning their own infrastructure
seriously, that is the entire reason the extra effort is worth it. You
are not renting the authority over your network. You hold it.