NetBird is an open source mesh VPN built on WireGuard. A management service distributes peer lists and keys, and each device then builds direct encrypted tunnels to the other peers, with NAT traversal and relays handled automatically. In this tutorial you will install the NetBird client on Ubuntu 24.04 servers, enroll them with a setup key, replace the default allow-all rule with group-based access policies, and give your peers access to a private subnet through a routing peer.
Prerequisites
To follow this guide you need:
- Two or more servers running Ubuntu 24.04 LTS, for example CubePath VPS instances, each with a non-root user that has
sudoprivileges. - A NetBird account. This guide uses the hosted management service at
https://app.netbird.io. If you run your own NetBird management server, everything works the same, but you add--management-url https://your_netbird_domainto thenetbird upcommand. - Outbound UDP and HTTPS allowed from the servers. NetBird does not need any inbound port opened on the peers.
Step 1 - Adding the NetBird APT repository
NetBird publishes signed packages for Debian and Ubuntu. Install the tools needed to fetch the key:
sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
Download and convert the repository key:
curl -fsSL https://pkgs.netbird.io/debian/public.key | sudo gpg --dearmor -o /etc/apt/keyrings/netbird-archive-keyring.gpg
Add the repository:
echo "deb [signed-by=/etc/apt/keyrings/netbird-archive-keyring.gpg] https://pkgs.netbird.io/debian stable main" | sudo tee /etc/apt/sources.list.d/netbird.list
Refresh the package index:
sudo apt update
The output should include a line for pkgs.netbird.io without any NO_PUBKEY error.
Step 2 - Installing the NetBird client
Install the headless client. The netbird package contains the CLI and the daemon; the separate netbird-ui package is only needed on desktops:
sudo apt install -y netbird
Check the version:
netbird version
0.x.y
The daemon runs as a systemd service called netbird. Check that it is active:
sudo systemctl status netbird
● netbird.service - Netbird
Loaded: loaded (/etc/systemd/system/netbird.service; enabled; preset: enabled)
Active: active (running) since ...
If systemd reports Unit netbird.service could not be found, register and start the service with the client itself:
sudo netbird service install
sudo netbird service start
Repeat Steps 1 and 2 on every server that should join the network.
Step 3 - Creating a setup key
Servers have no browser, so instead of the interactive SSO login you enroll them with a setup key. A setup key is a token that registers peers in your account and can place them into groups automatically.
In the NetBird dashboard:
- Open Setup Keys and click Create Setup Key.
- Name it
servers. - Enable Make this key reusable so you can enroll several machines with it, and set an expiration such as 7 days.
- Under Auto-assigned groups, type
serversand create the group. - Click Create Setup Key and copy the key.
Treat the key like a password: anyone who has it can add a machine to your network until it expires or you revoke it.
Step 4 - Connecting the peers
On each server, bring the connection up with the setup key. Replace your_setup_key with the key you copied:
sudo netbird up --setup-key your_setup_key
Connected
For a self-hosted management server, add --management-url https://your_netbird_domain to the same command. The client stores its configuration, so after a reboot the daemon reconnects on its own.
Check the connection status:
sudo netbird status
Daemon version: 0.x.y
CLI version: 0.x.y
Management: Connected
Signal: Connected
Relays: 3/3 Available
Nameservers: 0/0 Available
FQDN: server-1.netbird.cloud
NetBird IP: 100.92.14.37/16
Interface type: Kernel
Quantum resistance: false
Networks: -
Peers count: 1/1 Connected
Management: Connected and Signal: Connected mean the client is enrolled. Each peer gets an address from the 100.64.0.0/10 range on a WireGuard interface called wt0:
ip -brief address show wt0
wt0 UNKNOWN 100.92.14.37/16
The new peers also appear under Peers in the dashboard, already members of the servers group.
Step 5 - Testing connectivity between peers
List the peers that this server can see, with their NetBird IPs, DNS names and connection type:
sudo netbird status --detail
Look for Connection type: P2P for a direct tunnel, or Relayed when NAT prevents one. Both are encrypted end to end.
Ping another peer by its NetBird DNS name or IP. Replace the name with one from the previous output:
ping -c 3 server-2.netbird.cloud
PING server-2.netbird.cloud (100.92.201.8) 56(84) bytes of data.
64 bytes from 100.92.201.8: icmp_seq=1 ttl=64 time=1.12 ms
64 bytes from 100.92.201.8: icmp_seq=2 ttl=64 time=0.98 ms
64 bytes from 100.92.201.8: icmp_seq=3 ttl=64 time=1.01 ms
This works right away because a new account has a policy named Default that lets every peer reach every other peer on every port.
Step 6 - Restricting access with groups and policies
The Default policy is convenient for testing but too broad for production. A typical setup is: web servers may reach database servers on the database port, and administrators may reach everything over SSH.
First organize the peers into groups. In Peers, click a peer, and in Assigned Groups add it to web or db as appropriate. You can also create a separate setup key per role with its own auto-assigned group.
Then create the policies under Access Control > Policies:
- Click Add Policy.
- Set Protocol to
TCP, Source toweb, Destination todband Ports to5432(or3306for MySQL). - Leave the direction one way (source to destination), name the policy
web-to-dband save it. - Add a second policy from your admin group (for example, the group your laptop belongs to) to
Allwith ProtocolTCPand Port22, namedadmin-ssh.
Finally, open the Default policy and disable it. From now on, NetBird only allows traffic that one of your policies permits.
Verify from a web server that the database port is reachable:
nc -vz db-1.netbird.cloud 5432
Connection to db-1.netbird.cloud (100.92.201.8) 5432 port [tcp/postgresql] succeeded!
A port you did not allow, such as 22 from a web server to a database server, should now time out:
nc -vz -w 5 db-1.netbird.cloud 22
nc: connect to db-1.netbird.cloud (100.92.201.8) port 22 (tcp) timed out: Operation now in progress
NoteNetBird policies filter traffic that arrives over the
wt0interface. They do not replace the host firewall for the server's public interface. Keep UFW enabled for public traffic.
Step 7 - Reaching a private subnet through a routing peer
Peers can also reach machines that do not run NetBird, such as a private network between your servers or an office LAN. One peer inside that network acts as a routing peer: it receives traffic from the mesh and forwards it into the subnet, masquerading it with its own address so the destination hosts need no extra routes.
In the dashboard:
- Open Networks and click Add Network. Name it
private-lan. - Click Add Resource, enter the subnet, for example
10.10.0.0/24, and assign it to a group such asprivate-lan-hosts. - Click Add Routing Peer and select a peer that has an interface in
10.10.0.0/24. - Create a policy with Source set to the group that should have access (for example,
web) and Destination set toprivate-lan-hosts.
On a peer in the source group, check that the route was received:
sudo netbird status --detail | grep -A3 -i networks
Then test a host in the subnet:
ping -c 3 10.10.0.20
If you use two routing peers for the same network, NetBird fails over between them automatically.
Managing the client
A few commands cover day-to-day use:
| Command | What it does |
|---|---|
sudo netbird status --detail | Shows every peer, connection type, latency and received routes |
sudo netbird down | Disconnects this machine from the mesh |
sudo netbird up | Reconnects with the stored configuration |
sudo netbird debug bundle | Collects logs and state for troubleshooting |
To remove a server permanently, run sudo netbird down, uninstall with sudo apt remove netbird, and delete the peer in the dashboard.
Troubleshooting
Management: Disconnected in the status output. The client cannot reach the management service over HTTPS. Check DNS and outbound connectivity, then read the client log:
sudo tail -n 50 /var/log/netbird/client.log
Peers are connected but ping fails. Check that an enabled policy allows the traffic between the two groups, and that the destination peer belongs to the group you think it does. After disabling the Default policy this is the most common cause.
Every connection shows Relayed. Direct connections need outbound UDP. If a strict egress firewall blocks UDP, NetBird falls back to its relays, which work but add latency. Allow outbound UDP from the servers to get P2P tunnels.
Setup key rejected. The key may have expired, been revoked, or reached its usage limit. Create a new key in Setup Keys.
Conclusion
Your Ubuntu 24.04 servers are now part of a NetBird WireGuard mesh, enrolled with a setup key, isolated by group-based policies instead of the default allow-all rule, and able to reach a private subnet through a routing peer. As next steps, you can enable DNS management to resolve internal names across the mesh, connect your SSO provider so team members log in with their existing accounts, and enable Posture Checks to only allow peers with a minimum client version.
