NetBird: Self-Hosted Mesh-VPN mit Zugriffskontrolle
Wer bisher wg-easy nutzt, kennt das Setup: ein zentraler Server, Port-Forwarding am Router, und jeder Client bekommt manuell einen Tunnel. Das funktioniert gut, solange du allein unterwegs bist. Aber was passiert, wenn du Freunden und Familie Zugang zu deinem Media-Stack geben willst — ohne ihnen gleich das gesamte Homelab zu oeffnen?
Mit der 4-Schichten-Sicherheit aus iptables-Hooks, Router-Firewall und NPM Access Lists laesst sich das loesen, aber der Aufwand waechst mit jedem neuen User und jedem neuen Dienst. Und wenn deine Gaeste hinter CGNAT sitzen (Mobilfunk, DS-Lite), wird Port-Forwarding zum Gluecksspiel.
Die Loesung: NetBird — ein Open-Source Mesh-VPN auf WireGuard-Basis mit eingebautem Identity Provider, Gruppen, Policies und automatischem NAT-Traversal. Self-hosted auf einem guenstigen VPS, mit Dashboard zur Verwaltung.
Was ist NetBird?
NetBird ist ein Open-Source Mesh-VPN, das auf WireGuard aufbaut und automatische Peer-to-Peer-Verbindungen zwischen allen Teilnehmern herstellt. Im Gegensatz zu klassischen Hub-Spoke-VPNs wie wg-easy gibt es keinen zentralen Engpass — der Datenverkehr fliesst direkt zwischen den Peers.
Die wichtigsten Unterschiede zu wg-easy:
| Feature | wg-easy | NetBird |
|---|---|---|
| Topologie | Hub-Spoke (alles ueber Server) | Mesh (Peer-to-Peer) |
| NAT-Traversal | Manuelles Port-Forwarding | Automatisch (STUN/TURN/Relay) |
| Client-Verwaltung | Manuell (QR-Codes, Configs) | Setup Keys + Dashboard |
| Zugriffskontrolle | iptables-Hooks, manuell | Eingebautes RBAC (Gruppen + Policies) |
| Identity Provider | Keiner | Eingebetteter Dex IdP |
| Multi-User | Umstaendlich | Native Unterstuetzung |
| Routing | NAT/Masquerade auf Server | Routing Peers pro Netzwerk-Segment |
NetBird besteht aus drei Hauptkomponenten:
- Management Server: Verwaltet Peers, Gruppen, Policies und Netzwerk-Konfiguration
- Signal Server: Vermittelt die initiale Peer-to-Peer-Verbindung (Signaling)
- Relay Server: Fallback fuer Peers die keine direkte Verbindung aufbauen koennen (TURN)
Alle drei sind im offiziellen netbirdio/netbird-server Docker-Image kombiniert. Dazu kommt ein Web-Dashboard und ein Traefik Reverse Proxy fuer SSL-Terminierung.
NetBird ist Open Source (BSD-3): github.com/netbirdio/netbird
NetBird vs. wg-easy vs. Tailscale
Bevor du dich fuer eine Loesung entscheidest, hier der Vergleich:
| Kriterium | wg-easy | NetBird (self-hosted) | Tailscale |
|---|---|---|---|
| Topologie | Hub-Spoke | Mesh | Mesh |
| Zugangskontrolle | Manuell (iptables, NPM) | Eingebaut (RBAC) | Eingebaut (ACLs) |
| NAT-Traversal | Port-Forwarding noetig | Automatisch | Automatisch |
| Self-Hosted | Ja | Ja | Teilweise (Headscale) |
| Identity Provider | Keiner | Dex (eingebettet) | Google/Microsoft/GitHub |
| Kosten | Kostenlos | Kostenlos + VPS (~6 EUR/Monat) | Kostenlos bis 100 Geraete |
| Komplexitaet | Niedrig | Mittel | Niedrig |
| Clients | WireGuard nativ | NetBird Client | Tailscale Client |
| Netzwerk-Routing | Einfach (1 Subnet) | Flexibel (pro VLAN) | Flexibel |
| Dashboard | Einfache Web-UI | Vollstaendige Management-UI | Cloud-Dashboard |
Wann welches Tool?
- wg-easy: Du bist der einzige User, Port-Forwarding ist moeglich, du willst maximale Einfachheit
- NetBird: Mehrere User mit unterschiedlichen Berechtigungen, CGNAT-Problematik, du willst volle Kontrolle ueber deine Daten
- Tailscale: Du willst Mesh-VPN ohne eigene Infrastruktur, Cloud-IdP ist akzeptabel
Architektur
NetBird selbst zu hosten bedeutet: ein VPS mit drei Docker-Containern. Die gesamte Intelligenz steckt im netbird-server — er vereint Management, Signal und Relay in einem Image.
NetBird Self-Hosted: 3 Container auf dem VPS, Routing Peers im Homelab
| Container | Image | Ports | Funktion |
|---|---|---|---|
netbird-server |
netbirdio/netbird-server:latest |
80, 33073, 10000/UDP | Management + Signal + Relay + Dex IdP |
netbird-dashboard |
netbirdio/dashboard:latest |
80 | Web-UI fuer Verwaltung |
netbird-traefik |
traefik:v3.6 |
443, 33073, 10000/UDP | SSL-Terminierung, Let’s Encrypt |
Der eingebettete Dex IdP stellt OAuth2-Tokens aus. Der Dashboard- und CLI-Client authentifizieren sich ueber Dex. Die Konfiguration liegt als SQLite-Datenbank im Docker Volume — kein PostgreSQL, kein externer IdP noetig.
sequenceDiagram
participant C as Client (Peer)
participant M as Management Server
participant S as Signal Server
participant P as Anderer Peer
C->>M: Authentifizierung (Setup Key/JWT)
M-->>C: Peer-Konfiguration + Netzwerk-Info
C->>S: Verbindungsanfrage an Peer P
S-->>P: Signaling (ICE Candidates)
C->>P: WireGuard Peer-to-Peer Tunnel
Note over C,P: Direkter Traffic (kein Server dazwischen)
alt NAT-Traversal fehlgeschlagen
C->>M: Fallback ueber Relay (TURN)
M-->>P: Relay-Verbindung
end
Voraussetzungen
Fuer die Installation brauchst du:
VPS-Seite:
- VPS mit oeffentlicher IPv4 (ab ~4 EUR/Monat bei Netcup, wie im Pangolin-Post beschrieben)
- Domain mit A-Record auf die VPS-IP
- Docker + Docker Compose
- SSH-Zugang
Im Homelab (optional, fuer Routing):
- Leichtgewichtige VMs oder Container (1 pro VLAN das erreichbar sein soll)
- Docker auf diesen VMs
Der VPS braucht nicht viel Leistung. NetBird’s Management Server ist genuegsam — 1 vCPU und 2 GB RAM reichen fuer Dutzende Peers.
Server-Installation auf dem VPS
DNS einrichten
Erstelle einen A-Record fuer deine Domain, der auf die IP deines VPS zeigt:
1
netbird.example.com. IN A 203.0.113.42
Warte nach dem DNS-Eintrag 5-10 Minuten, bevor du weitermachst. Let’s Encrypt braucht eine funktionierende DNS-Aufloesung.
Quickstart-Script ausfuehren
NetBird bietet ein offizielles Installationsskript, das alle drei Container konfiguriert und startet. Fuer die Ausfuehrung ueber SSH muss ein kleiner Patch angewendet werden:
1
2
3
4
5
6
7
8
# Script herunterladen
curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh -o getting-started.sh
# Patch: interaktiven Input entfernen (fuer SSH-Ausfuehrung)
sed -i 's/< \/dev\/tty//' getting-started.sh
# Ausfuehren
bash getting-started.sh
Das Script fragt nach:
- Domain:
netbird.example.com - Let’s Encrypt E-Mail: Deine E-Mail fuer Zertifikats-Benachrichtigungen
Nach Abschluss laufen drei Container:
1
docker ps --format "table \t\t"
1
2
3
4
NAMES STATUS PORTS
netbird-server Up 2 hours 80/tcp, 33073/tcp, 10000/udp
netbird-dashboard Up 2 hours 80/tcp
netbird-traefik Up 2 hours 0.0.0.0:443->443/tcp, ...
Konfigurationsdateien
Das Script erstellt drei Dateien unter /opt/:
1
2
3
4
/opt/
├── docker-compose.yml # Container-Definitionen
├── config.yaml # Server-Konfiguration (Management, Signal, Relay, Dex)
└── dashboard.env # Dashboard-Umgebungsvariablen
Die wichtigste ist config.yaml — sie enthaelt die Dex-Konfiguration mit den OAuth2-Clients, den Encryption Key fuer die SQLite-Datenbank und die Server-Einstellungen.
Sichere die
config.yamlan einem sicheren Ort. DerencryptionKeydarin verschluesselt Benutzerdaten in der Datenbank. Ohne diesen Key sind die Daten nicht wiederherstellbar.
Erster Login
- Oeffne
https://netbird.example.comim Browser - Du wirst zum Dex-Login weitergeleitet
- Erstelle beim ersten Login einen Admin-Account
- Nach der Anmeldung siehst du das NetBird Dashboard
Im Dashboard siehst du zunaechst einen leeren Peer-Ueberblick. Peers erscheinen erst, wenn sich Clients verbinden.
Schritt-fuer-Schritt: NetBird konfigurieren
Nach der Installation stehst du vor einem leeren Dashboard. Dieser Abschnitt zeigt die empfohlene Reihenfolge, um NetBird von Null zu einem funktionierenden Setup mit Zugriffskontrolle zu konfigurieren. Die einzelnen Konzepte werden in den folgenden Kapiteln vertieft.
Halte dich an diese Reihenfolge — spaetere Schritte bauen auf frueheren auf. Gruppen muessen existieren bevor du sie in Networks oder Policies verwenden kannst.
Schritt 1: Default Policy deaktivieren
Dashboard → Access Control → Policies
Die vorinstallierte “Default” Policy erlaubt allen Peers die Kommunikation untereinander. Deaktiviere sie als Erstes, damit nur explizit erlaubter Traffic fliesst.
→ Klicke auf die “Default” Policy → Toggle auf Disabled → Save
Schritt 2: Gruppen anlegen
Dashboard → Access Control → Groups → Create Group
Lege zwei Arten von Gruppen an:
| Schritt | Gruppenname | Zweck |
|---|---|---|
| 2a | media-viewers |
Benutzergruppe fuer Endbenutzer (z.B. Freunde, Familie) |
| 2b | media-admins |
Benutzergruppe fuer vertrauenswuerdige Nutzer |
| 2c | homelab-admins |
Benutzergruppe fuer Admins mit Vollzugriff |
| 2d | svc-arr-stack |
Ressourcengruppe fuer den Media-Stack |
| 2e | svc-homelab-infra |
Ressourcengruppe fuer die gesamte Homelab-Infrastruktur |
Benutzergruppen und Ressourcengruppen sind technisch identisch — die Trennung ist rein konzeptionell. Benutzergruppen werden spaeter Peers zugewiesen, Ressourcengruppen werden Network Resources zugewiesen.
Schritt 3: Network und Resources anlegen
Dashboard → Networks → Create Network
- Erstelle ein Network (z.B. “Homelab”)
- Fuege Resources hinzu — jede Resource ist ein IP-Bereich der ueber NetBird erreichbar sein soll:
| Resource-Name | Adresse | Zugewiesene Gruppe |
|---|---|---|
| ARR-Stack | 10.0.60.141/32 |
svc-arr-stack |
| VLAN 60 - Server | 10.0.60.0/24 |
svc-homelab-infra |
| VLAN 2 - LAN | 10.0.2.0/24 |
svc-homelab-infra |
| VLAN 30 - IoT | 10.0.30.0/24 |
svc-homelab-infra |
| VLAN 45 - DMZ | 10.0.45.0/24 |
svc-homelab-infra |
| VLAN 50 - Guest | 10.0.50.0/24 |
svc-homelab-infra |
Die Gruppenzuweisung bei jeder Resource ist entscheidend: sie macht die Gruppe zur Ressourcengruppe, auf die Policies spaeter verweisen.
Schritt 4: Routing Peers verbinden und als Router zuweisen
- Starte auf jeder Routing-Peer-VM den NetBird-Client (siehe Docker Compose fuer Routing Peers)
- Zurueck im Dashboard: Networks → Dein Network → Bei jeder Resource einen Router hinzufuegen
- Waehle den passenden Routing Peer (der im selben VLAN steht) und aktiviere Masquerade
| Resource | Router (Peer) |
|---|---|
| ARR-Stack / VLAN 60 | netbird-server |
| VLAN 2 - LAN | netbird-lan |
| VLAN 30 - IoT | netbird-iot |
| VLAN 45 - DMZ | netbird-dmz |
| VLAN 50 - Guest | netbird-guest |
Schritt 5: Policies erstellen
Dashboard → Access Control → Policies → Create Policy
Jede Policy verbindet eine Benutzergruppe (Source) mit einer Ressourcengruppe (Destination):
| Policy | Source → Destination | Protokoll | Ports |
|---|---|---|---|
| Media Viewers - Playback | media-viewers → svc-arr-stack |
TCP | 32400, 8096, 7575, 5055 |
| Media Admins - ARR Stack | media-admins → svc-arr-stack |
TCP | 32400, 8096, 7575, 5055, 8989, 7878, … |
| Homelab Admins - Full | homelab-admins → svc-homelab-infra |
ALL | Alle |
Schritt 6: Benutzer einladen
Dashboard → Users → Invite User
- E-Mail-Adresse des Benutzers eingeben
- Auto-Assign Groups setzen (z.B.
media-viewers) - Invite absenden → Der User erhaelt einen Link zum Anlegen seines Dex-Accounts
Alternativ fuer Headless-Clients: Setup Keys → Create Setup Key mit entsprechenden Auto Groups.
Ergebnis: Nach diesen 6 Schritten hast du ein funktionierendes Setup — eingeladene Benutzer landen automatisch in der richtigen Gruppe, Policies greifen sofort, und die VLAN-Isolation im Homelab bleibt erhalten. Die folgenden Kapitel vertiefen jedes Thema im Detail.
VLAN-Routing: NetBird-Clients im Homelab
Hier wird es interessant. NetBird kann nicht nur Clients miteinander verbinden — es kann auch Netzwerkrouten zu internen Subnets verteilen. Damit koennen externe Clients auf Dienste in deinem Homelab zugreifen, ohne dass diese Dienste oeffentlich erreichbar sind.
Das Konzept: 1 Routing Peer pro VLAN
In meinem Homelab gibt es fuenf VLANs, die ueber die UDM Pro voneinander isoliert sind. Statt eines einzigen VPN-Endpunkts, der Zugang zu allem haette, nutze ich einen NetBird-Client (Routing Peer) pro VLAN:
Jeder Routing Peer sitzt in genau einem VLAN und routet nur dieses Subnet
VLAN-Platzierung: Warum es wichtig ist
Dieses Design ist zentral fuer die Sicherheit. Jeder Routing Peer ist eine leichtgewichtige VM, die in genau einem VLAN platziert ist. Er kann physisch nur das Netzwerk erreichen, in dem er sich befindet:
- Ein Peer in VLAN 60 (Server) kann
10.0.60.0/24routen — Proxmox, GitLab, Plex - Ein Peer in VLAN 2 (LAN) kann
10.0.2.0/24routen — Desktops, NAS, Drucker - Ein Peer in VLAN 30 (IoT) kann
10.0.30.0/24routen — Home Assistant, Zigbee
Ein Peer in VLAN 60 kann nicht in VLAN 2 oder VLAN 30 routen, selbst wenn er wollte — die VLANs sind auf Layer 2 isoliert. Das bedeutet: wenn eine Gruppe nur Zugriff auf den Media-Stack in VLAN 60 braucht, bekommt sie eine Route nur ueber den Peer in VLAN 60. Alles andere bleibt unsichtbar.
Dieses Konzept unterscheidet sich fundamental von einem einzelnen VPN-Server, der im Routing-VLAN steht und per NAT/Masquerade Zugang zu allem hat. Hier entscheidet die physische Platzierung des Peers, welche Netze ueberhaupt erreichbar sind.
Docker Compose fuer Routing Peers
Jeder Routing Peer laeuft als Docker-Container mit dem NetBird-Client:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
services:
netbird-client:
image: netbirdio/netbird:latest
container_name: netbird-client
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_ADMIN
- SYS_RESOURCE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv4.conf.all.src_valid_mark=1
environment:
- NB_MANAGEMENT_URL=https://netbird.example.com
- NB_SETUP_KEY=${NB_SETUP_KEY}
volumes:
- netbird_config:/etc/netbird
volumes:
netbird_config:
Die Capabilities NET_ADMIN und SYS_ADMIN sind noetig, damit der Client WireGuard-Interfaces erstellen und Routen setzen kann. ip_forward=1 erlaubt das Weiterleiten von Paketen.
1
2
# Starten auf jeder Routing-Peer-VM
NB_SETUP_KEY="<setup-key>" docker compose up -d
Routing Peers im Ueberblick
| Peer | VLAN | IP | Subnet |
|---|---|---|---|
| netbird-lan | 2 (LAN) | 10.0.2.65 | 10.0.2.0/24 |
| netbird-iot | 30 (IoT) | 10.0.30.65 | 10.0.30.0/24 |
| netbird-dmz | 45 (DMZ) | 10.0.45.65 | 10.0.45.0/24 |
| netbird-guest | 50 (Guest) | 10.0.50.65 | 10.0.50.0/24 |
| netbird-server | 60 (Server) | 10.0.60.45 | 10.0.60.0/24 |
Netzwerk-Routen im Dashboard konfigurieren
Nachdem alle Routing Peers verbunden sind, muessen im Dashboard die Netzwerk-Routen eingerichtet werden:
- Networks → Create Network (z.B. “Homelab”)
- Resources hinzufuegen — z.B.
10.0.60.0/24mit Name “VLAN 60 Full” - Jeder Resource eine Ressourcengruppe zuweisen (z.B.
svc-homelab-infra) - Router hinzufuegen — den entsprechenden Routing Peer als Router fuer die Resource waehlen
- Masquerade aktivieren (damit Antwort-Pakete den Rueckweg finden)
flowchart TB
subgraph VPS["VPS (netbird.example.com)"]
MS[Management Server]
end
subgraph HL["Homelab"]
subgraph V60["VLAN 60 — Server"]
RP60[netbird-server<br/>10.0.60.45]
SVC60[Proxmox, GitLab<br/>Plex, Jellyfin]
end
subgraph V45["VLAN 45 — DMZ"]
RP45[netbird-dmz<br/>10.0.45.65]
SVC45[NPM, Caddy]
end
subgraph V2["VLAN 2 — LAN"]
RP2[netbird-lan<br/>10.0.2.65]
SVC2[Desktops, NAS]
end
subgraph V30["VLAN 30 — IoT"]
RP30[netbird-iot<br/>10.0.30.65]
SVC30[Home Assistant]
end
subgraph V50["VLAN 50 — Guest"]
RP50[netbird-guest<br/>10.0.50.65]
SVC50[Gast-Geraete]
end
end
EC[Externer Client] -.->|WireGuard Mesh| MS
MS -.-> RP60 & RP45 & RP2 & RP30 & RP50
RP60 --> SVC60
RP45 --> SVC45
RP2 --> SVC2
RP30 --> SVC30
RP50 --> SVC50
style VPS fill:#1a2332,stroke:#4ecdc4,color:#fff
style V60 fill:#0d1117,stroke:#4ecdc4,color:#fff
style V45 fill:#0d1117,stroke:#2a9d8f,color:#fff
style V2 fill:#0d1117,stroke:#4ecdc4,color:#fff
style V30 fill:#0d1117,stroke:#2a9d8f,color:#fff
style V50 fill:#0d1117,stroke:#4ecdc4,color:#fff
RBAC: Gruppen und Policies
Die eigentliche Staerke von NetBird: Role-Based Access Control direkt im VPN. Statt iptables-Regeln und NPM Access Lists definierst du im Dashboard, welche Benutzergruppe auf welche Ressourcen zugreifen darf.
Drei Ebenen: Benutzergruppen werden ueber Policies mit Ressourcengruppen verbunden
Gruppenkonzept
NetBird kennt zwei Arten von Gruppen:
| Gruppe | Typ | Zweck | Mitglieder |
|---|---|---|---|
media-viewers |
Benutzer | Freunde, Familie — nur Medienkonsum | Eingeladene User |
media-admins |
Benutzer | Vertrauenswuerdige User — Medienverwaltung | Ausgewaehlte User |
homelab-admins |
Benutzer | Voller Zugriff auf alles | Nur Admins |
svc-arr-stack |
Ressource | ARR-Stack VM (10.0.60.141/32) | Automatisch (Network Resource) |
svc-homelab-infra |
Ressource | Alle Homelab-VLANs | Automatisch (Network Resources) |
Benutzergruppen enthalten Peers (Clients). Ressourcengruppen enthalten Netzwerk-Resources (IPs/Subnets). Die Verbindung zwischen beiden stellen Policies her.
Ressourcengruppen: Das Bindeglied zwischen Netzwerk und Policy
Ressourcengruppen sind ein zentrales Konzept in NetBird, das auf den ersten Blick leicht uebersehen wird. Sie verbinden die Netzwerk-Konfiguration (welche Subnets existieren, welcher Peer routet wohin) mit der Zugriffskontrolle (welche Benutzergruppe darf wohin).
Wie entstehen Ressourcengruppen?
Wenn du im Dashboard unter Networks eine Resource anlegst (z.B. 10.0.60.141/32 fuer den ARR-Stack), weist du ihr eine oder mehrere Gruppen zu. Diese Gruppen werden dadurch zu Ressourcengruppen — sie repraesentieren ein Ziel, auf das Policies verweisen koennen.
| Ressourcengruppe | Zugeordnete Resources | Routing Peer |
|---|---|---|
svc-arr-stack |
ARR-Stack (10.0.60.141/32) |
netbird-server (VLAN 60) |
svc-homelab-infra |
VLAN 60 (10.0.60.0/24), VLAN 2 (10.0.2.0/24), VLAN 30 (10.0.30.0/24), VLAN 45 (10.0.45.0/24), VLAN 50 (10.0.50.0/24) |
Je 1 Peer pro VLAN |
Der Zusammenhang:
1
2
3
4
5
6
7
Network "Homelab"
└── Resource "ARR-Stack" (10.0.60.141/32)
│ └── Gruppe: svc-arr-stack ← Ressourcengruppe
│ └── Router: netbird-server ← Routing Peer
└── Resource "VLAN 60 Full" (10.0.60.0/24)
└── Gruppe: svc-homelab-infra ← Ressourcengruppe
└── Router: netbird-server ← Routing Peer
Eine Ressourcengruppe kann mehrere Resources aus verschiedenen VLANs buendeln. svc-homelab-infra enthaelt z.B. alle fuenf VLAN-Subnets — ein Peer in homelab-admins bekommt ueber eine einzige Policy Zugriff auf das gesamte Homelab. Umgekehrt ist svc-arr-stack bewusst eng gefasst: nur die eine VM mit den Media-Diensten.
Ressourcengruppen sind normale NetBird-Gruppen — du kannst sie unter Groups im Dashboard sehen. Der Unterschied zu Benutzergruppen ist rein konzeptionell: Benutzergruppen enthalten Peers, Ressourcengruppen werden Resources zugewiesen. Technisch sind beide dasselbe Objekt.
Policies definieren
Jede Policy hat eine Source (Benutzergruppe), eine Destination (Ressourcengruppe), ein Protokoll und optionale Ports:
| Policy | Source | Destination | Protokoll | Ports |
|---|---|---|---|---|
| Media Viewers - Playback | media-viewers |
svc-arr-stack |
TCP | 32400 (Plex), 8096 (Jellyfin), 7575 (Homarr), 5055 (Seerr) |
| Media Admins - ARR Stack | media-admins |
svc-arr-stack |
TCP | Alle Media-Ports + 8989 (Sonarr), 7878 (Radarr), 8686 (Lidarr), 6767 (Bazarr), 9696 (Prowlarr), … |
| Homelab Admins - Full Access | homelab-admins |
svc-homelab-infra |
ALL | Alle Ports |
Vergiss nicht, die Default Policy zu deaktivieren! Standardmaessig erlaubt NetBird allen Peers die Kommunikation untereinander. Fuer ein sicheres Setup sollte nur explizit erlaubter Traffic fliessen.
Policy-Logik: Was passiert bei einem Zugriff?
Wenn ein externer Client versucht, auf einen Dienst zuzugreifen, prueft NetBird:
- In welcher Benutzergruppe ist der Peer?
- Gibt es eine Policy, die dieser Gruppe Zugriff auf das Ziel erlaubt?
- Stimmt das Protokoll und der Port ueberein?
flowchart TD
A[Client will auf 10.0.60.141:32400 zugreifen] --> B{Client in welcher Gruppe?}
B -->|media-viewers| C{Policy vorhanden?}
B -->|media-admins| D{Policy vorhanden?}
B -->|keine Gruppe| X[DENY - Kein Zugriff]
C -->|Media Viewers - Playback| E{Port 32400 erlaubt?}
D -->|Media Admins - ARR Stack| F{Port 32400 erlaubt?}
E -->|Ja, in Port-Liste| G[ALLOW - Plex erreichbar]
F -->|Ja, in Port-Liste| G
style G fill:#1a3d1a,stroke:#27c93f,color:#fff
style X fill:#3d1a1a,stroke:#f85149,color:#fff
- Beispiel 1 — Viewer will Plex schauen (Port 32400):
- Peer ist in
media-viewers→ Policy “Media Viewers - Playback” matcht → Port 32400 ist erlaubt → Zugriff gewaehrt - Beispiel 2 — Viewer will Sonarr oeffnen (Port 8989):
- Peer ist in
media-viewers→ Policy “Media Viewers - Playback” matcht → Port 8989 ist nicht in der Port-Liste → Zugriff verweigert - Beispiel 3 — Viewer will Proxmox erreichen (Port 8006):
- Peer ist in
media-viewers→ Ziel10.0.60.15gehoert zusvc-homelab-infra→ Keine Policy verbindetmedia-viewersmitsvc-homelab-infra→ Zugriff verweigert
Benutzer einladen
Das Einladen neuer Benutzer ist einer der groessten Vorteile gegenueber wg-easy. Kein manuelles Erstellen von WireGuard-Configs, kein QR-Code-Scanning — ein Setup Key reicht.
Setup Keys erstellen
Im Dashboard unter Setup Keys → Create Setup Key:
| Parameter | Wert | Erklaerung |
|---|---|---|
| Name | Media Viewer Invite | Beschreibender Name |
| Type | Reusable | Mehrfach verwendbar |
| Expires in | 90 Tage | Automatische Deaktivierung |
| Usage Limit | 10 | Max. 10 Geraete mit diesem Key |
| Auto Groups | media-viewers |
Neue Peers werden automatisch zugewiesen |
| Ephemeral | Nein | Peers bleiben nach Disconnect registriert |
Der entscheidende Parameter ist Auto Groups: Jeder Peer der sich mit diesem Setup Key verbindet, wird automatisch der Gruppe media-viewers zugeordnet. Die Policies greifen sofort — ohne manuellen Eingriff.
Einladung verschicken
Im Dashboard unter Users → Invite User kannst du Benutzer per E-Mail einladen. Der eingeladene User erhaelt einen Link, ueber den er seinen Dex-Account anlegt (Benutzername + Passwort). Danach muss er nur noch den NetBird-Client installieren und sich anmelden.
Hier eine Vorlage die du zusammen mit dem Invite-Link per E-Mail oder Messenger verschicken kannst:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Hey <NAME>,
ich habe dir Zugang zu meinem Media-Server eingerichtet.
Du kannst damit Filme, Serien und Musik streamen — von ueberall aus.
## Einrichtung (5 Minuten)
### 1. Account anlegen
Klicke auf den Einladungslink und lege dir einen Account an
(Benutzername + Passwort):
<INVITE_LINK>
### 2. NetBird installieren
- Windows: https://app.netbird.io/install#windows
- macOS: https://app.netbird.io/install#macos
- Linux: https://app.netbird.io/install#linux
- iOS: App Store -> "NetBird"
- Android: Play Store -> "NetBird"
### 3. Verbindung herstellen
NetBird oeffnen, dann unter Einstellungen:
- Management URL auf https://netbird.example.com aendern
- "Anmelden" klicken und mit deinem neuen Account einloggen
Alternativ via Terminal:
netbird up --management-url https://netbird.example.com
### 4. Media-Dashboard oeffnen
Sobald die VPN-Verbindung steht (gruenes Symbol), oeffne im Browser:
https://homarr.example.com
Dort findest du Plex, Jellyfin und Seerr (Filme/Serien wuenschen).
## Troubleshooting
- VPN verbindet nicht? Pruefe ob NetBird laeuft und die Management URL stimmt.
- Dashboard nicht erreichbar? Pruefe ob das NetBird-Symbol "Connected" zeigt.
- Bei Problemen melde dich einfach bei mir.
Passe
<NAME>und<INVITE_LINK>an. Die Management URL und das Dashboard muessen auf deine eigene Domain zeigen.
Setup Keys vs. Invite Links: Setup Keys (siehe oben) eignen sich fuer automatisiertes Enrollment — z.B. Routing Peers oder Headless-Clients. Fuer Endbenutzer ist der Invite-Link ueber das Dashboard der einfachere Weg, weil der User sich per Login authentifiziert statt einen Key eingeben zu muessen.
Client-Installation
NetBird hat Clients fuer alle gaengigen Plattformen:
| Plattform | Installation |
|---|---|
| Windows | Download von app.netbird.io |
| macOS | Download oder brew install netbird |
| Linux | curl -fsSL https://pkgs.netbird.io/install.sh \| sudo bash |
| iOS | App Store → “NetBird” |
| Android | Play Store → “NetBird” |
Nach der Installation verbindet sich der Client je nach Enrollment-Methode:
1
2
3
4
5
# Invite-Link (Benutzer mit Dex-Account) — oeffnet Browser fuer Login
netbird up --management-url https://netbird.example.com
# Setup Key (Headless/automatisiert) — kein Login noetig
netbird up --management-url https://netbird.example.com --setup-key <SETUP_KEY>
Oder ueber die GUI: Management URL eintragen, dann entweder per Login anmelden (Invite) oder Setup Key eingeben (Headless).
Was passiert nach der Verbindung?
Zwei Enrollment-Wege: Invite-Link (Endbenutzer) und Setup Key (Headless) fuehren beide zu aktiven Policies
Invite-Link (Endbenutzer):
- Der Admin erstellt einen Invite im Dashboard (Users → Invite User) und waehlt dabei optional Auto-Assign Groups (z.B.
media-viewers) - Der User klickt den Invite-Link und legt seinen Dex-Account an (Benutzername + Passwort)
- Im NetBird-Client traegt er die Management URL ein und meldet sich mit seinen Credentials an
- Der Management Server registriert den Peer, weist eine WireGuard-IP zu (100.x.x.x) und ordnet den Peer automatisch den vordefinierten Gruppen zu
- Alle Policies die
media-viewersals Source haben, werden sofort aktiv — ohne weiteren Admin-Eingriff
Setup Key (Headless/automatisiert):
- Der Client authentifiziert sich mit dem Setup Key beim Management Server
- Der Peer wird registriert und automatisch den Auto Groups des Keys zugewiesen
- Policies greifen sofort — ohne manuellen Admin-Eingriff
Das ist der Kernunterschied zu wg-easy: bei wg-easy musst du nach jedem neuen Client iptables-Regeln anpassen, NPM Access Lists aktualisieren und ggf. Router-Firewallregeln aendern. Bei NetBird definierst du die Regeln einmal, und jeder neue Client erbt sie automatisch ueber die Gruppenzuordnung.
RBAC per API automatisieren
Das Dashboard ist praktisch fuer gelegentliche Aenderungen. Aber wenn du ein reproduzierbares Setup willst — z.B. nach einem Fresh Install alles wiederherstellen — brauchst du die API.
Token via Device Flow
NetBird nutzt OAuth2 mit dem eingebetteten Dex IdP. Da Dex kein Password Grant unterstuetzt, verwendest du den Device Flow:
1
2
3
4
# Schritt 1: Device Code anfordern
curl -sk -X POST https://netbird.example.com/oauth2/device/code \
-d 'client_id=netbird-cli' \
-d 'scope=openid profile email'
Die Antwort enthaelt einen user_code und eine verification_uri. Oeffne die URI im Browser und gib den Code ein.
1
2
3
4
5
# Schritt 2: Token abholen (nach Browser-Bestaetigung)
curl -sk -X POST https://netbird.example.com/oauth2/token \
-d 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
-d 'device_code=<DEVICE_CODE>' \
-d 'client_id=netbird-cli'
Das Token ist 24 Stunden gueltig.
Reproduzierbares Setup-Script
Mit dem Token kannst du das gesamte RBAC-Setup automatisieren. Hier ein Auszug aus dem Script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env bash
set -euo pipefail
NB_API="https://netbird.example.com/api"
AUTH="Authorization: Bearer ${NB_TOKEN}"
api() {
local method="$1" endpoint="$2"
shift 2
curl -sk -X "$method" -H "$AUTH" -H "Content-Type: application/json" \
"${NB_API}${endpoint}" "$@"
}
# Gruppen anlegen
GRP_VIEWERS=$(api POST /groups -d '{"name":"media-viewers"}' | jq -r '.id')
GRP_ADMINS=$(api POST /groups -d '{"name":"media-admins"}' | jq -r '.id')
GRP_HOMELAB=$(api POST /groups -d '{"name":"homelab-admins"}' | jq -r '.id')
GRP_SVC_ARR=$(api POST /groups -d '{"name":"svc-arr-stack"}' | jq -r '.id')
GRP_SVC_INFRA=$(api POST /groups -d '{"name":"svc-homelab-infra"}' | jq -r '.id')
# Network + Routing Peer
NETWORK_ID=$(api POST /networks -d '{
"name": "Homelab",
"description": "Homelab-Infrastruktur ueber alle VLANs"
}' | jq -r '.id')
# Resource: ARR-Stack
api POST "/networks/${NETWORK_ID}/resources" -d "{
\"name\": \"ARR-Stack\",
\"address\": \"10.0.60.141/32\",
\"groups\": [\"${GRP_SVC_ARR}\"]
}"
# Policy: Media Viewers - Playback
api POST /policies -d "{
\"name\": \"Media Viewers - Playback\",
\"enabled\": true,
\"rules\": [{
\"name\": \"Media Viewers - Playback\",
\"enabled\": true,
\"action\": \"accept\",
\"bidirectional\": true,
\"protocol\": \"tcp\",
\"ports\": [\"32400\", \"8096\", \"7575\", \"5055\"],
\"sources\": [\"${GRP_VIEWERS}\"],
\"destinations\": [\"${GRP_SVC_ARR}\"]
}]
}"
# Setup Key fuer Viewer
SETUP_KEY=$(api POST /setup-keys -d "{
\"name\": \"Media Viewer Invite\",
\"type\": \"reusable\",
\"auto_groups\": [\"${GRP_VIEWERS}\"],
\"expires_in\": 7776000,
\"usage_limit\": 10
}" | jq -r '.key')
echo "Setup Key: ${SETUP_KEY}"
Das vollstaendige Script mit allen Gruppen, Networks, Resources und Policies liegt im Repository unter
vps02/netbird-rbac-setup.sh.
Vergleich: NetBird RBAC vs. wg-easy 4-Schichten
Wie verhaelt sich NetBirds eingebautes RBAC zur 4-Schichten-Sicherheit mit wg-easy?
| Kriterium | wg-easy + 4-Schichten | NetBird RBAC |
|---|---|---|
| Netzwerk-Isolation | VLAN + Router-Firewall | VLAN + Routing Peers (1 pro VLAN) |
| Per-Client Firewall | iptables PostUp/PostDown Hooks | Policies (Gruppen → Ports) |
| Reverse Proxy Schutz | NPM Access Lists (IP-basiert) | Nicht noetig (Policies auf Port-Ebene) |
| Neuen Dienst freigeben | iptables-Regel + NPM ACL + ggf. Router-FW | Port zur Policy hinzufuegen |
| Neuen User einladen | WireGuard Config erstellen + iptables-Hook + NPM ACL | Setup Key verschicken |
| User-Berechtigungen aendern | Hook-Script anpassen + NPM ACL | Gruppenverschiebung im Dashboard |
| Komplexitaet | Hoch (4 Schichten manuell pflegen) | Mittel (1 Stelle: Dashboard/API) |
| Automatisierung | Moeglich aber aufwaendig | Native API + Setup Keys |
| Reproduzierbarkeit | Scripts fuer jede Schicht | Ein API-Script fuer alles |
Fazit: Die 4-Schichten-Architektur mit wg-easy ist maechtig und lehrreich, aber der Wartungsaufwand skaliert schlecht mit der Anzahl an Usern und Diensten. NetBird konsolidiert die Zugriffskontrolle an einer Stelle — was bei einem einzelnen Admin fuer mehrere externe User deutlich praktikabler ist.
Backup und Wartung
SQLite-Datenbanken sichern
Die kritischen Daten liegen im Docker Volume opt_netbird_data:
| Datei | Inhalt |
|---|---|
store.db |
Peers, Gruppen, Policies, Networks, Routes, Setup Keys |
idp.db |
Dex Identity Provider (User, OAuth2 Clients) |
events.db |
Audit-Log (Events, Login-Versuche) |
1
2
3
4
# Manuelles Backup vor Aenderungen
sudo docker compose -f /opt/docker-compose.yml stop
sudo cp -a /var/lib/docker/volumes/opt_netbird_data/_data/ ~/backups/netbird-$(date +%Y%m%d)/
sudo docker compose -f /opt/docker-compose.yml up -d
Automatisiere das Backup per Cron. Ein taeglicher Job um 03:00 Uhr mit Rotation der letzten 7 Tage reicht fuer die meisten Setups.
Updates
1
2
3
4
5
# Images aktualisieren
cd /opt && docker compose pull
# Container neu starten
docker compose up -d
NetBird veroeffentlicht regelmaessig Updates. Pruefe vor dem Update die Release Notes auf Breaking Changes.
Troubleshooting
Client verbindet nicht
1
2
3
4
5
# Client-Status pruefen
netbird status
# Detailliertes Log
netbird up --log-level debug
Haeufige Ursachen:
- Falsche Management URL: Muss
https://netbird.example.comsein (mit HTTPS) - Abgelaufener Setup Key: Pruefe im Dashboard unter Setup Keys das Ablaufdatum
- Firewall auf dem Client: Port 443 (Management) und 51820/UDP (WireGuard) muessen offen sein
Routing funktioniert nicht
1
2
3
4
5
6
7
8
9
# Auf dem Routing Peer pruefen
docker exec netbird-client netbird status
# IP-Forwarding pruefen
docker exec netbird-client sysctl net.ipv4.ip_forward
# Erwartete Ausgabe: net.ipv4.ip_forward = 1
# WireGuard-Interface pruefen
docker exec netbird-client ip addr show wt0
Haeufige Ursachen:
- Masquerade nicht aktiviert: Im Dashboard bei der Network Route “Masquerade” einschalten
- Routing Peer offline:
docker logs netbird-clientauf der VM pruefen - Falsches VLAN: Peer muss im selben VLAN wie das Ziel-Subnet stehen
Dashboard nicht erreichbar
1
2
3
4
5
6
7
8
# Container-Status
docker ps -a | grep netbird
# Traefik-Logs (SSL-Probleme)
docker logs netbird-traefik --tail 50
# Let's Encrypt Zertifikat pruefen
docker exec netbird-traefik cat /letsencrypt/acme.json | jq '.Certificates'
Haeufige Ursachen:
- DNS nicht aufgeloest: A-Record pruefen mit
dig netbird.example.com - Port 443 blockiert: Firewall auf dem VPS pruefen
- Let’s Encrypt Rate Limit: Maximal 5 Zertifikate pro Domain pro Woche
Fazit
NetBird trifft den Sweet Spot zwischen wg-easy und Tailscale:
- Einfacher als wg-easy bei Multi-User-Setups: Keine manuellen iptables-Regeln, keine NPM Access Lists, keine Router-Firewall-Anpassungen pro User
- Mehr Kontrolle als Tailscale: Volle Datenhoheit, eigener IdP, keine Cloud-Abhaengigkeit
- NAT-Traversal out-of-the-box: Kein Port-Forwarding noetig, funktioniert auch hinter CGNAT
Die Kombination aus Routing Peers (1 pro VLAN) und RBAC (Gruppen → Policies → Resources) ergibt eine saubere Architektur, die mit jedem neuen User besser skaliert als die 4-Schichten-Loesung. Einen neuen Freund zum Plex einladen? Setup Key verschicken, fertig.
Fuer den persoenlichen Zugang bleibt wg-easy eine exzellente Wahl — einfach, robust, bewaehrt. Aber sobald du Homelab-Dienste mit anderen teilen willst, ohne dabei Kompromisse bei der Sicherheit zu machen, lohnt sich der Umstieg auf NetBird.
Ressourcen
- NetBird Website — Offizielle Seite mit Dokumentation
- NetBird GitHub — Quellcode (BSD-3 Lizenz)
- NetBird Docs: Self-Hosting — Offizielle Installationsanleitung
- WireGuard — Das Protokoll unter der Haube
- Dex IdP — Der eingebettete Identity Provider
- WireGuard: Modernes VPN fuer dein Homelab mit wg-easy — WireGuard Grundlagen-Post
- VPN-Zugangskontrolle: 4-Schichten-Sicherheit mit wg-easy — Granularer Zugriff mit Hooks und Firewall
- Pangolin: Selbstgehosteter Reverse Proxy — VPS-Setup und WireGuard-Tunnel