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 sudo privileges.
  • 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_domain to the netbird up command.
  • 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:

  1. Open Setup Keys and click Create Setup Key.
  2. Name it servers.
  3. Enable Make this key reusable so you can enroll several machines with it, and set an expiration such as 7 days.
  4. Under Auto-assigned groups, type servers and create the group.
  5. 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:

  1. Click Add Policy.
  2. Set Protocol to TCP, Source to web, Destination to db and Ports to 5432 (or 3306 for MySQL).
  3. Leave the direction one way (source to destination), name the policy web-to-db and save it.
  4. Add a second policy from your admin group (for example, the group your laptop belongs to) to All with Protocol TCP and Port 22, named admin-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

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:

  1. Open Networks and click Add Network. Name it private-lan.
  2. Click Add Resource, enter the subnet, for example 10.10.0.0/24, and assign it to a group such as private-lan-hosts.
  3. Click Add Routing Peer and select a peer that has an interface in 10.10.0.0/24.
  4. Create a policy with Source set to the group that should have access (for example, web) and Destination set to private-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:

CommandWhat it does
sudo netbird status --detailShows every peer, connection type, latency and received routes
sudo netbird downDisconnects this machine from the mesh
sudo netbird upReconnects with the stored configuration
sudo netbird debug bundleCollects 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.