A complete guide to deploying your own Zero Trust network using NetBird and Authentik as identity provider. No port forwarding, no VPN concentrator, no exposed attack surface — just encrypted WireGuard tunnels between your machines, anywhere in the world.

How NetBird works

NetBird separates control plane from data plane. The VPS runs the control plane — it never sees your decrypted traffic. Data travels directly between peers via encrypted WireGuard, or relayed through coturn when direct connection is impossible (symmetric NAT). In both cases, traffic remains end-to-end encrypted.

Three planes — what runs where
CONTROL PLANE — VPSManagement ServerDashboard, API, config — via :443Signal ServerWireGuard session coordinationcoturn (STUN/TURN)NAT traversal + relay fallbackTraefik handles TLS — Let's EncryptDATA PLANE — PEER TO PEERWireGuard P2PDirect tunnel when possibleWireGuard via TURNEncrypted relay (symmetric NAT)Your data never transits the VPSunencrypted — not even via TURN.PROXY PLANENetBird Reverse ProxyClientless ZTNA via browserSSO — AuthentikAuthentication before forwardingProxy PeerMakes the TCP connection to the app

Reference architecture

A VPS (Hetzner) hosts NetBird and Authentik. An OPNsense firewall on-site acts as routing peer, giving all authenticated peers access to every internal subnet — without NetBird clients on the machines themselves.

HostRoleAddressNetBird client
VPS (Hetzner)NetBird management + Authentik sidecarPublic IPAuthentik container has one
OPNsenseFirewall + Routing Peer (all VLANs)192.168.1.1 / .10.1 / .20.1Yes — official plugin
Raspberry PiNextcloud, Pi-hole192.168.10.10Optional
NASStorage (TrueNAS)192.168.10.20Optional
DesktopWork machine192.168.1.50Yes
LaptopMobile peer — access from anywhereVariable (DHCP)Yes

1. Prerequisites & DNS

VPS — NetBird only

1 vCPU · 2 GB RAM · 20 GB SSD
Ubuntu 22.04 LTS — Hetzner CX22

VPS — NetBird + Authentik

2 vCPU · 4 GB RAM · 20 GB SSD
Authentik alone needs ~2 GB RAM.

Firewall ports

PortProtoPurposeNote
80TCPHTTP → HTTPS redirectRequired for Let’s Encrypt TLS challenge
443TCPEverything — Dashboard, API, SignalAll proxied by Traefik
3478UDPSTUN / TURNcoturn NAT traversal
49152–65535UDPTURN relay rangecoturn relay ports
Do not open port 33073 externally — internal gRPC between Docker containers. Do not open 10000 — Signal is proxied through Traefik on 443.

DNS records

TypeNameValueNote
AnetbirdYOUR.VPS.IPMain NetBird domain
CNAME*.netbirdnetbird.your-domain.comWildcard — required for proxy subdomains
If using Cloudflare, set both records to DNS only (grey cloud). The wildcard CNAME ensures subdomains like cloud.netbird.your-domain.com resolve to the VPS.

VPS dependencies

# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

# Required tools
sudo apt install -y jq curl

2. Install NetBird

The official install script handles everything: generates a complete docker-compose.yml, sets up Traefik with automatic TLS, configures coturn, and optionally enables the built-in reverse proxy.

Run the official install script

curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bash

When prompted, enter your domain name — e.g. netbird.your-domain.com.

Choose Traefik as reverse proxy

Press **Enter** to accept the default `[0] Traefik`. Traefik is bundled in the compose file and handles Let's Encrypt certificates automatically.

Enable the NetBird Proxy service

Do you want to enable the NetBird Proxy service? [y/N]: y

Enables the Reverse Proxy feature in the dashboard, used later to expose Authentik and internal apps without any direct port exposure.

Verify all containers are running

cd /opt/netbird
docker compose ps
# Expected: management, signal, relay, coturn, traefik, proxy, dashboard

Create the initial local admin account

Open `https://netbird.your-domain.com/setup` — create an admin account with email + password. This temporary account will be replaced by Authentik later.
The /setup page is only available when no users exist.

Generated files

FilePurpose
docker-compose.ymlFull stack: management, signal, relay, coturn, traefik, dashboard, proxy
config.yamlCombined server config
dashboard.envDashboard container environment variables
proxy.envProxy container config

3. Deploy Authentik as a sidecar

Authentik runs in its own Docker stack on the same VPS, with a NetBird client container added to it. That client container registers as a peer and acts as routing peer for the Authentik Docker subnet. The NetBird reverse proxy then exposes Authentik — no ports opened on the VPS.

Create the Authentik directory

mkdir /opt/authentik && cd /opt/authentik
curl -fsSL https://goauthentik.io/docker-compose.yml -o docker-compose.yml

Generate credentials

# PostgreSQL password
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '=+/')" >> .env

# Authentik secret key — min 50 characters required
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -hex 32)" >> .env

cat .env  # verify both values are present

Create a Setup Key for the Authentik sidecar

NetBird dashboard → **Setup Keys → Add Setup Key**:
FieldValue
Namevps-services
TypeReusable
Expiry90 days

Copy the generated key — you’ll use it in the next step.

Add the NetBird client sidecar to docker-compose.yml

Add the network stanza to `postgresql`, `server`, and `worker` services:
networks:
  authentik-net:
    ipv4_address: 172.20.0.10  # .10 server / .20 postgres / .30 worker

Then append the sidecar service and top-level network definition:

  netbird:
    image: netbirdio/netbird:latest
    cap_add: [NET_ADMIN, SYS_ADMIN]
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=0
    environment:
      - NB_SETUP_KEY=<paste-setup-key-here>
      - NB_MANAGEMENT_URL=https://netbird.your-domain.com
    restart: unless-stopped
    networks:
      authentik-net:
        ipv4_address: 172.20.0.2

networks:
  authentik-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
Static IPs are important — the reverse proxy needs the exact IP of the Authentik server container (172.20.0.10:9000) to forward traffic correctly.

Start Authentik

docker compose up -d
docker compose logs -f server | grep -i startup

After ~1 minute, the vps-services peer should appear in the NetBird dashboard under Peers.

Complete Authentik initial setup

Temporarily open port `9000` on your VPS firewall, then navigate to:
http://YOUR.VPS.IP:9000/if/flow/initial-setup/

Create the Authentik admin account. Once done, close port 9000 immediately.

Do not skip closing port 9000. The reverse proxy is the only intended entry point once everything is configured.

4. Expose Authentik via NetBird Reverse Proxy

Before linking Authentik as an IdP, it needs to be accessible via a stable HTTPS URL. The NetBird reverse proxy handles this — no direct internet exposure, TLS automatic via Traefik.

Create the VPS Services network

NetBird dashboard → **Networks → Add Network**:
FieldValue
NameVPS Services
ResourceAdd subnet 172.20.0.0/24
Routing PeerSelect vps-services

Add Authentik as a Reverse Proxy service

Dashboard → **Reverse Proxy → Services → Add HTTP/S Service**:
TabFieldValue
ServiceSubdomainauth → full URL: auth.netbird.your-domain.com
ServiceProxy Peervps-services
AuthenticationAuth methodNone — Authentik manages its own auth
AdvancedPass Host HeaderEnable
No Auth is correct here. Authentik is itself the authentication layer. Setting No Auth for other services is a security issue — not for the IdP.

Add Target

FieldValue
Protocolhttp://
IP172.20.0.10
Port9000

Verify and close port 9000

Navigate to `https://auth.netbird.your-domain.com` — you should see the Authentik login page over HTTPS with a valid certificate. Then **close port 9000** on the VPS firewall permanently.

A four-step OIDC handshake: create the provider in Authentik, create the application, get the redirect URL from NetBird, paste it back into Authentik.

Create the OAuth2/OpenID provider in Authentik

Authentik → **Admin Interface → Applications → Providers → Create**:
FieldValue
TypeOAuth2/OpenID Provider
NameNetBird
Authorization flowdefault-provider-authorization-explicit-consent
Client typeConfidential
Redirect URIsLeave empty for now
Signing KeySelect any cert (authentik Self-signed Certificate)

Note the Client ID and Client Secret from the provider detail page.

Create the Authentik application

FieldValue
NameNetBird
Slugnetbird
ProviderSelect the NetBird provider

Add Authentik as IdP in NetBird — copy the Redirect URL

NetBird → **Settings → Identity Providers → Add Identity Provider**:
FieldValue
TypeGeneric OIDC
Client IDFrom Authentik step 1
Client SecretFrom Authentik step 1
Issuerhttps://auth.netbird.your-domain.com/application/o/netbird/

Copy the Redirect URL that NetBird generates — do not click “Add Provider” yet.

Paste the Redirect URL back into Authentik

Authentik → **Providers → NetBird → Edit** → under **Redirect URIs/Origins** → Add → mode: **Strict** → paste the URL → Update.
Always use Strict mode, not Regex. Any mismatch causes an “Invalid redirect URI” error at login time.

Complete the NetBird IdP configuration

Return to the NetBird tab and click **Add Provider**. Authentik is now configured as the identity provider.

6. User management & ownership transfer

Test the Authentik login flow

Open a private browser window → navigate to `https://netbird.your-domain.com`. Click the **Authentik** button, authenticate with your Authentik credentials.

Approve the pending user

Switch back to the local admin account → **Team → Users** → approve the pending Authentik user.

Transfer ownership

In **Team → Users**, find the Authentik-managed user and change their role to **Owner**.

Verify, then delete the local account

Log out → log back in using Authentik → confirm full admin access. Only then delete the original local user.
Do not delete the local account before confirming Authentik login works. Losing access to both accounts locks you out entirely, with no recovery path.

7. JWT group sync

NetBird can automatically mirror Authentik group memberships into NetBird groups via the JWT token’s groups claim. Adding a user to a group in Authentik instantly grants them the corresponding NetBird access.

Enable "Include claims in id_token" in the Authentik provider

Authentik → **Providers → NetBird → Edit** → under **Advanced protocol settings** → enable **Include claims in id_token**. Ensure the `profile` and `groups` scopes are listed.

Enable JWT group sync in NetBird

NetBird → **Settings → Groups**:
FieldValue
JWT group syncEnable
JWT claimgroups
JWT allow groupsOptional — restrict to specific groups only

8. Peers & Setup Keys

A peer is any machine with the NetBird client installed. Once registered, each peer gets a stable IP in the 100.64.0.0/10 CGNAT range and communicates via encrypted WireGuard tunnels.

Install the client

# Linux — Debian / Ubuntu
curl -fsSL https://pkgs.netbird.io/install.sh | sh
netbird up --management-url https://netbird.your-domain.com
# OPNsense — official plugin
# System → Firmware → Plugins → search "netbird" → install os-netbird
# Then: VPN → NetBird → Settings → Management URL: https://netbird.your-domain.com

Setup Keys

One-time key

Used once, then consumed. Ideal for manually registering a specific machine.

Reusable key

Multiple uses until expiry. Ideal for Ansible, Terraform, or Docker-based deployments.

# Register a peer non-interactively
netbird up \
  --management-url https://netbird.your-domain.com \
  --setup-key XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

9. Networks & Resources

A Network is NetBird’s top-level logical grouping. It contains Resources (subnets), one or more Routing Peers (gateways), and optionally Services (reverse proxy endpoints). Access Policies control which peer groups can reach the Network.

Network Routes (legacy)Networks (recommended)
GranularityOne CIDR at a timeFull site — multiple CIDRs grouped
Reverse ProxyNot integratedIntegrated as “Services”
Access ControlPer routePer Network — covers all resources
Best for1–2 simple subnetsAny multi-subnet site
Use Networks for any homelab or multi-VLAN environment. Network Routes are a legacy feature maintained for backwards compatibility.

10. Routing Peers

A routing peer announces one or more subnets to the mesh. Remote peers send traffic for those subnets to the routing peer, which forwards it natively. OPNsense is the ideal routing peer for a homelab — it already routes all VLANs natively.

The golden rule: the routing peer must be the machine that can natively reach the subnet it announces — ideally the default gateway of that subnet.

For the return path to work, machines in the announced subnet must have OPNsense as their default gateway. If a machine uses a different gateway, TCP responses go to the wrong router and the connection hangs — data flows one way only.

11. Reverse Proxy — clientless ZTNA

The Reverse Proxy exposes an internal app via a public HTTPS URL with SSO auth, without the end user needing to install the NetBird client. The proxy peer is the machine that makes the TCP connection — it must reach the destination natively.

Configure a service

Add HTTP/S Service

FieldValueNotes
SubdomaincloudFull URL: cloud.netbird.your-domain.com
Proxy PeeropnsenseThe machine making the TCP connection

Authentication tab → Add SSO

Select Authentik. Users must authenticate via Authentik + MFA before the request is forwarded.
Never leave a service as No Auth unless the service is itself an auth provider. The proxy subdomain is not a secret — anyone can find it.

Add Target — always select Resource, not Peer

FieldValueNotes
TypeResourceAllows entering an internal LAN IP
ResourceVLAN 10 Services
Protocolhttp://
IP192.168.10.10
Port80
Skip TLSOffEnable only for self-signed certs (e.g. Proxmox :8006)
Selecting Peer instead of Resource locks you into the peer’s NetBird IP (100.64.x.x) — you cannot target an internal subnet IP that way.

12. Access Control Policies

Policies define which peer groups can reach which Networks or Resources. The default is deny all — without a policy, no peer can access any Network.

13. Split DNS

NetBird can push nameserver configuration to peers so internal hostnames resolve while connected to the mesh.

DNS → Add Nameserver

FieldValue
Nameserver IP192.168.1.1 — OPNsense / Unbound
Domainhome (or lan, internal)
Groupsadmins, family

Configure host overrides in OPNsense Unbound

nas.home        → 192.168.10.20
nextcloud.home  → 192.168.10.10
opnsense.home   → 192.168.1.1

Test from any peer

nslookup nas.home       # → 192.168.10.20
nslookup nextcloud.home # → 192.168.10.10
nslookup google.com     # → still resolves via public DNS

14. OPNsense firewall rules

This is the most commonly missed step. OPNsense blocks all inter-interface traffic by default. Without these rules, routing peer traffic will be silently dropped — even though everything in NetBird is correctly configured.

Rule 1 — Allow NetBird peers to reach your subnets

Firewall → Rules → [WireGuard / NetBird interface] → Add rule:

FieldValue
ActionPass
InterfaceWireGuard / NetBird (wg0)
ProtocolAny
Source100.64.0.0/10 — NetBird CGNAT range
Destination192.168.0.0/16 — your homelab subnets

Rule 2 — Exclude NetBird traffic from NAT masquerade

Firewall → NAT → Outbound → switch to Hybrid mode → add a No-NAT rule:

FieldValue
InterfaceLAN (and each VLAN interface)
Source100.64.0.0/10
DestinationYour homelab subnets
TranslationNo NAT
With No NAT in place: internal hosts see the real peer IP (100.64.x.x) and reply to it → OPNsense routes the reply back through WireGuard → the connection completes correctly in both directions.

15. Use cases

Full admin access from anywhere

netbird up
# → Authentik login + MFA
# → full access to 192.168.1.0/24, 192.168.10.0/24, 192.168.20.0/24

ssh user@192.168.10.10   # Raspberry Pi
ssh user@192.168.10.20   # NAS shell

Share Nextcloud with a friend — no client needed

Create a user in Authentik → assign to group guests (synced via JWT) → send them https://cloud.netbird.your-domain.com. They open a browser, log in via Authentik, complete MFA, and access Nextcloud. Nothing installed on their side.

Remote access for family members

Family members install the NetBird client on their phones → authenticate via Authentik → JWT sync assigns them to the family group → they get access to LAN + VLAN 10 only, not the management VLAN or IoT network.