Eintrag

NetBird: Self-Hosted Mesh-VPN mit Zugriffskontrolle

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 Architektur NetBird Architektur 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.yaml an einem sicheren Ort. Der encryptionKey darin verschluesselt Benutzerdaten in der Datenbank. Ohne diesen Key sind die Daten nicht wiederherstellbar.

Erster Login

  1. Oeffne https://netbird.example.com im Browser
  2. Du wirst zum Dex-Login weitergeleitet
  3. Erstelle beim ersten Login einen Admin-Account
  4. 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

DashboardAccess ControlPolicies

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 DisabledSave

Schritt 2: Gruppen anlegen

DashboardAccess ControlGroupsCreate 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

DashboardNetworksCreate Network

  1. Erstelle ein Network (z.B. “Homelab”)
  2. 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

  1. Starte auf jeder Routing-Peer-VM den NetBird-Client (siehe Docker Compose fuer Routing Peers)
  2. Zurueck im Dashboard: Networks → Dein Network → Bei jeder Resource einen Router hinzufuegen
  3. 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

DashboardAccess ControlPoliciesCreate Policy

Jede Policy verbindet eine Benutzergruppe (Source) mit einer Ressourcengruppe (Destination):

Policy Source → Destination Protokoll Ports
Media Viewers - Playback media-viewerssvc-arr-stack TCP 32400, 8096, 7575, 5055
Media Admins - ARR Stack media-adminssvc-arr-stack TCP 32400, 8096, 7575, 5055, 8989, 7878, …
Homelab Admins - Full homelab-adminssvc-homelab-infra ALL Alle

Schritt 6: Benutzer einladen

DashboardUsersInvite User

  1. E-Mail-Adresse des Benutzers eingeben
  2. Auto-Assign Groups setzen (z.B. media-viewers)
  3. Invite absenden → Der User erhaelt einen Link zum Anlegen seines Dex-Accounts

Alternativ fuer Headless-Clients: Setup KeysCreate 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:

VLAN-Routing Konzept VLAN-Routing Konzept 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/24 routen — Proxmox, GitLab, Plex
  • Ein Peer in VLAN 2 (LAN) kann 10.0.2.0/24 routen — Desktops, NAS, Drucker
  • Ein Peer in VLAN 30 (IoT) kann 10.0.30.0/24 routen — 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:

  1. NetworksCreate Network (z.B. “Homelab”)
  2. Resources hinzufuegen — z.B. 10.0.60.0/24 mit Name “VLAN 60 Full”
  3. Jeder Resource eine Ressourcengruppe zuweisen (z.B. svc-homelab-infra)
  4. Router hinzufuegen — den entsprechenden Routing Peer als Router fuer die Resource waehlen
  5. 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.

RBAC-Modell RBAC-Modell 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:

  1. In welcher Benutzergruppe ist der Peer?
  2. Gibt es eine Policy, die dieser Gruppe Zugriff auf das Ziel erlaubt?
  3. 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 → Ziel 10.0.60.15 gehoert zu svc-homelab-infra → Keine Policy verbindet media-viewers mit svc-homelab-infraZugriff 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 KeysCreate 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 UsersInvite 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?

Einladungs-Workflow Einladungs-Workflow Zwei Enrollment-Wege: Invite-Link (Endbenutzer) und Setup Key (Headless) fuehren beide zu aktiven Policies

Invite-Link (Endbenutzer):

  1. Der Admin erstellt einen Invite im Dashboard (UsersInvite User) und waehlt dabei optional Auto-Assign Groups (z.B. media-viewers)
  2. Der User klickt den Invite-Link und legt seinen Dex-Account an (Benutzername + Passwort)
  3. Im NetBird-Client traegt er die Management URL ein und meldet sich mit seinen Credentials an
  4. Der Management Server registriert den Peer, weist eine WireGuard-IP zu (100.x.x.x) und ordnet den Peer automatisch den vordefinierten Gruppen zu
  5. Alle Policies die media-viewers als Source haben, werden sofort aktiv — ohne weiteren Admin-Eingriff

Setup Key (Headless/automatisiert):

  1. Der Client authentifiziert sich mit dem Setup Key beim Management Server
  2. Der Peer wird registriert und automatisch den Auto Groups des Keys zugewiesen
  3. 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.com sein (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-client auf 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

Dieser Eintrag ist vom Autor unter CC BY 4.0 lizensiert.