Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Server & Netzwerk 04.06.2026 · 10 min Lesezeit

Headscale selbst hosten: Tailscale-Mesh-VPN ohne Cloud-Abhängigkeit für KMU

Headscale ersetzt den Tailscale Control Server auf eigener Infrastruktur: Installation auf Ubuntu, Reverse Proxy mit TLS, Nutzer und Pre-Auth-Keys, ACL-Policy, Subnet-Router und Exit-Node mit Headscale 0.29.

Geprüft am 29.09.2026 · für headscale 0.29.4

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Kompakter Server auf einem Wandregal, per blauem Netzwerkkabel mit Router und zugeklapptem Laptop auf einem Holzschreibtisch verbunden

Mit WireGuard braucht jedes neue Gerät ein Schlüsselpaar, Einträge auf jedem Peer und Firewall-Anpassungen. Tailscale nimmt das ab, betreibt den Koordinationsserver aber in der eigenen Cloud und rechnet pro Nutzer ab. Headscale ist eine Open-Source-Reimplementierung dieses Control Servers für Ihren eigenen Server, ohne Geräte-Limits.

Voraussetzungen

  • Ubuntu-Server 22.04 LTS oder 24.04 LTS (VPS oder dediziert, öffentlich erreichbar), x86_64 oder ARM64
  • Öffentliche IPv4-Adresse und ein FQDN (z. B. hs.example.com) mit DNS-A-Eintrag
  • Gültiges TLS-Zertifikat – Let's Encrypt via Certbot (Nginx) oder automatisch via Caddy
  • Offene Ports: TCP/443 (HTTPS), TCP/80 (Let's Encrypt, Weiterleitung), UDP/3478 (STUN, nur mit eingebettetem DERP-Server)
  • Mindestens 1 vCPU, 1 GB RAM, 10 GB SSD (für einige Dutzend Geräte)
  • Tailscale-Client auf jedem Endgerät (Windows, macOS, Linux, iOS, Android)
  • Grundkenntnisse Linux-Serverbetrieb und Nginx/Caddy-Konfiguration

Schritt 1: Headscale vs. Tailscale-Cloud vs. WireGuard – die richtige Wahl treffen

Alle drei Optionen basieren auf WireGuard, unterscheiden sich aber in Verwaltungsaufwand, Datensouveränität und Kosten:

KriteriumWireGuard (rein)Tailscale CloudHeadscale (self-hosted)
Peer-VerwaltungManuell je GerätAutomatischAutomatisch
NAT-TraversalManuell/keinAutomatisch (DERP)Automatisch (DERP)
DatensouveränitätVollständigUS-ServerVollständig
DSGVO-RisikoGeringMetadaten auf US-ServernGering (eigene Infra)
Geräte-LimitsKeineBegrenzt im kostenlosen TarifKeine
AbrechnungNur eigener ServerJe Nutzer und MonatNur eigener Server
EinrichtungsaufwandHochMinimalMittel (~90 Min.)

Empfehlung: Headscale eignet sich für KMU, die mehr als 3 Nutzer haben, Wert auf Datensouveränität legen und bereit sind, einen einfachen Linux-Server zu betreiben. Tailscale-Cloud bleibt die bessere Wahl, wenn das IT-Team sehr klein ist und SSO-Integration (Azure AD, Google) ohne eigene OIDC-Infrastruktur benötigt wird. Reines WireGuard ist dann sinnvoll, wenn ausschließlich Server-zu-Server-Verbindungen mit statischen IPs nötig sind. Aktuelle Tarife nennt die Preisseite von Tailscale.

Verifizieren: Sie haben einen Server mit öffentlicher IP, einen DNS-A-Eintrag für den Headscale-FQDN und die Freigabe, die Ports 80 und 443 dafür zu nutzen.

Schritt 2: Headscale installieren

Headscale wird als Debian-Paket ausgeliefert; die SQLite-Datenbank legt es selbst an.

# Headscale 0.29.4 herunterladen und installieren (Ubuntu 22.04/24.04)
HEADSCALE_VERSION="0.29.4"
HEADSCALE_ARCH="amd64"   # arm64 für ARM-Server
wget -O headscale.deb "https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
sudo apt install ./headscale.deb
sudo systemctl enable --now headscale

Headscale lauscht per Default nur auf 127.0.0.1:8080 (HTTP), 127.0.0.1:9090 (Metriken) und 127.0.0.1:50443 (gRPC). TLS terminiert hier der Reverse Proxy; alternativ holt Headscale selbst Let's-Encrypt-Zertifikate.

Verifizieren: headscale version zeigt 0.29.4, systemctl status headscale meldet active (running).

Schritt 3: Headscale konfigurieren

Passen Sie in /etc/headscale/config.yaml mindestens folgende Werte an (Schlüssel wie in der Beispielkonfiguration von Version 0.29):

# /etc/headscale/config.yaml (Auszug, übrige Werte wie ausgeliefert)
server_url: https://hs.example.com
listen_addr: 127.0.0.1:8080
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
trusted_proxies:
  - 127.0.0.1/32
  - ::1/128
tls_cert_path: ""
tls_key_path: ""
noise:
  private_key_path: /var/lib/headscale/noise_private.key
prefixes:
  v4: 100.64.0.0/10
  v6: fd7a:115c:a1e0::/48
database:
  type: sqlite
  sqlite:
    path: /var/lib/headscale/db.sqlite
log:
  level: info
policy:
  mode: file
  path: /etc/headscale/acl.json
dns:
  magic_dns: true
  base_domain: vpn.example.com
  nameservers:
    global:
      - 1.1.1.1
derp:
  server:
    enabled: false
  urls:
    - https://controlplane.tailscale.com/derpmap/default
  auto_update_enabled: true
  update_frequency: 3h

Wichtig: base_domain für MagicDNS (hier vpn.example.com) muss sich von der Server-URL-Domain (hs.example.com) unterscheiden, sonst entstehen DNS-Loops; kein abschließender Punkt. Bis zur Policy-Datei (Schritt 7) bleibt path: "", sonst startet Headscale nicht. Nach Änderungen: sudo systemctl restart headscale.

Verifizieren: sudo headscale configtest endet ohne Fehler, journalctl -u headscale -n 20 zeigt keine Meldungen zu unbekannten oder veralteten Schlüsseln.

Schritt 4: Reverse Proxy mit TLS einrichten

Tailscale-Clients erwarten HTTPS auf Port 443 mit einem gültigen Zertifikat. Zwei Optionen:

Option A: Nginx mit Certbot

# /etc/nginx/sites-available/headscale
server {
  listen 443 ssl;
  server_name hs.example.com;
  ssl_certificate /etc/letsencrypt/live/hs.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/hs.example.com/privkey.pem;

  location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host;
    proxy_buffering off;
  }
}

Zwingend: proxy_http_version 1.1, die Upgrade/Connection-Header und proxy_buffering off, sonst brechen langlebige WebSocket-Verbindungen ab. Ausführlich: Nginx als Reverse Proxy mit TLS einrichten.

Option B: Caddy (empfohlen – automatisches TLS)

# /etc/caddy/Caddyfile
hs.example.com {
  reverse_proxy 127.0.0.1:8080
}

Caddy holt und erneuert das Zertifikat automatisch und leitet WebSockets ohne Zusatzkonfiguration weiter. Cloudflare-Proxy (oranges Wolkensymbol) und Cloudflare Tunnel werden nicht unterstützt, da Cloudflare das Tailscale-Protokoll nicht korrekt weiterleitet; nur DNS-only (graues Symbol).

Verifizieren: curl -sI https://hs.example.com/health liefert HTTP/2 200 mit gültigem Zertifikat.

Schritt 5: Nutzer, Gruppen und Pre-Auth-Keys anlegen

„Users“ entsprechen den Tailscale-Namespaces; jedes Gerät gehört einem User, hier einer je Abteilung. Pre-Auth-Keys erwarten in 0.29 die numerische User-ID aus headscale users list:

# Nutzer (Abteilungen) anlegen
sudo headscale users create marketing
sudo headscale users create buchhaltung
sudo headscale users create it-admin

# IDs der User anzeigen
sudo headscale users list

# Einmaliger Pre-Auth-Key (24 Stunden gültig), USER_ID aus der Liste
sudo headscale preauthkeys create --user <USER_ID> --expiration 24h

# Wiederverwendbarer Key (z. B. für automatisiertes Onboarding, 30 Tage)
sudo headscale preauthkeys create --user <USER_ID> --reusable --expiration 720h

# Alle Keys auflisten
sudo headscale preauthkeys list

Sicherheitshinweis: Im Produktionsbetrieb kurzlebige Einmal-Keys statt wiederverwendbarer Keys mit langer Laufzeit nutzen. Der Key wird nur beim Anlegen vollständig angezeigt.

Verifizieren: sudo headscale users list zeigt die drei User, sudo headscale preauthkeys list die angelegten Keys mit Ablaufdatum.

Schritt 6: Geräte verbinden

Auf dem Client läuft der offizielle Tailscale-Client, der Login-Server wird als Parameter übergeben.

# Linux / macOS: Interaktiver Login (öffnet Browser-Authentifizierung)
tailscale up --login-server https://hs.example.com

# Mit Pre-Auth-Key (kein Browser-Login, ideal für Server-Onboarding)
tailscale up --login-server https://hs.example.com --authkey <PREAUTHKEY>

# Ohne Pre-Auth-Key: Node serverseitig registrieren
# (die Auth-ID aus der Ausgabe bzw. Webseite des Clients übernehmen)
sudo headscale auth register --user marketing --auth-id <AUTH_ID>

# Alle verbundenen Nodes anzeigen
sudo headscale nodes list

Windows und macOS haben GUI-Clients; auf iOS/Android tragen Sie den Server in der App unter „Account“ → „Use custom coordination server“ ein.

Verifizieren: sudo headscale nodes list zeigt das Gerät als online, auf dem Client meldet tailscale status eine IP aus 100.64.0.0/10.

Schritt 7: ACL-Policies für Abteilungstrennung

ACL-Policies nutzen das HuJSON-Format von Tailscale. Ohne Policy-Datei ist jeder Verkehr erlaubt, mit acls gilt Default-Deny. User schreiben Sie mit angehängtem @. IT-Admins erhalten Vollzugriff, Marketing und Buchhaltung bleiben intern:

// /etc/headscale/acl.json
{
  "groups": {
    "group:it-admin":    ["it-admin@"],
    "group:marketing":   ["marketing@"],
    "group:buchhaltung": ["buchhaltung@"]
  },
  "acls": [
    // IT-Admin darf alles
    { "action": "accept", "src": ["group:it-admin"], "dst": ["*:*"] },
    // Marketing darf nur innerhalb der eigenen Gruppe kommunizieren
    { "action": "accept", "src": ["group:marketing"], "dst": ["group:marketing:*"] },
    // Buchhaltung darf nur innerhalb der eigenen Gruppe kommunizieren
    { "action": "accept", "src": ["group:buchhaltung"], "dst": ["group:buchhaltung:*"] }
  ]
}
# Policy prüfen und neu einlesen (ohne Neustart)
sudo headscale policy check --file /etc/headscale/acl.json
sudo systemctl reload headscale

Beim ersten Mal path: /etc/headscale/acl.json unter policy eintragen und neu starten; spätere Änderungen übernimmt systemctl reload headscale. Tailscale empfiehlt für neue Policies Grants statt ACLs, Headscale unterstützt beide. Server-Absicherung: Linux-Server absichern mit UFW und Fail2ban.

Verifizieren: journalctl -u headscale -n 20 zeigt nach dem Reload keine Policy-Fehler. Ein Marketing-Gerät erreicht per tailscale ping ein anderes Marketing-Gerät, ein Buchhaltungs-Gerät dagegen nicht.

Schritt 8: Subnet-Router – LAN-Subnetz ins Tailnet einbinden

Ein Subnet-Router macht ein lokales Netz (z. B. Büro-LAN 192.168.10.0/24) im Tailnet erreichbar, ohne Tailscale auf jedem LAN-Gerät:

# IP-Forwarding aktivieren (persistent via sysctl)
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

# Subnetz bekanntmachen (auf dem Node, der das LAN sieht)
sudo tailscale up --login-server https://hs.example.com --advertise-routes=192.168.10.0/24

# Serverseitig: Route genehmigen (NODE_ID aus list-routes)
sudo headscale nodes list-routes
sudo headscale nodes approve-routes --identifier <NODE_ID> --routes 192.168.10.0/24

# Linux-Clients nehmen Subnet-Routen erst nach Freigabe an
sudo tailscale set --accept-routes

Fallstrick: Transient aktiviertes IP-Forwarding (echo 1 > /proc/sys/net/ipv4/ip_forward) geht beim Neustart verloren. Nutzen Sie /etc/sysctl.d/.

Verifizieren: sudo headscale nodes list-routes zeigt 192.168.10.0/24 unter „Approved“ und „Serving“, ein Client erreicht per ping eine Adresse im Büro-LAN.

Schritt 9: Exit-Node konfigurieren

Ein Exit-Node leitet den gesamten Internetverkehr eines Clients über einen Knoten, etwa für Homeoffice-Geräte mit Büro-IP:

# Auf dem Node, der als Exit-Node dienen soll:
sudo tailscale up --login-server https://hs.example.com --advertise-exit-node

# Serverseitig freischalten (0.0.0.0/0 genügt, ::/0 wird automatisch mit freigegeben)
sudo headscale nodes list-routes
sudo headscale nodes approve-routes --identifier <NODE_ID> --routes 0.0.0.0/0

# Auf dem Client-Gerät den Exit-Node nutzen:
sudo tailscale set --exit-node=<TAILSCALE-IP-DES-EXIT-NODES>

Auch der Exit-Node braucht aktiviertes IP-Forwarding wie in Schritt 8.

Verifizieren: Auf dem Client zeigt curl -s https://ifconfig.me die öffentliche IP des Exit-Nodes.

Schritt 10: DERP-Relay und Node-Verwaltung

DERP-Server leiten Verbindungen weiter, wenn keine direkte Verbindung zustande kommt. Default ist die öffentliche DERP-Map von Tailscale (alle 3 Stunden aktualisiert). Für Relays ohne Tailscale-Server betreiben Sie eigene DERP-Server und setzen urls: [].

# DERP-Status auf einem Client prüfen
tailscale debug derp-map
tailscale debug derp headscale

# Alle Nodes auflisten
sudo headscale nodes list

# Einzelnen Node manuell ablaufen lassen (z. B. bei Gerätetausch)
sudo headscale nodes expire --identifier <NODE_ID>

# Alle Routen prüfen
sudo headscale nodes list-routes

Key-Expiry: Nodes laufen per Default nie ab (Expiry = 0), bei Tailscale-Cloud nach 180 Tagen. Pre-Auth-Keys laufen nach einer Stunde ab. Ein Standard-Ablaufdatum setzen Sie mit node.expiry, einzelne Nodes lassen Sie mit headscale nodes expire ablaufen.

Verifizieren: tailscale debug derp-map listet die erwarteten DERP-Regionen, tailscale netcheck meldet eine erreichbare nächste Region.

Troubleshooting / Typische Fehler

  • Client verbindet sich nicht / „Invalid server URL“: Selbstsignierte Zertifikate werden abgelehnt. Zertifikat und Erneuerung prüfen (sudo certbot renew --dry-run).
  • WebSocket-Verbindung bricht ab: Nginx-Einstellungen aus Schritt 4 (HTTP/1.1, Upgrade/Connection, proxy_buffering off) prüfen.
  • Cloudflare-Proxy (orange) aktiv: Auf „DNS only“ (grau) umschalten.
  • MagicDNS löst Hostnamen nicht auf: base_domain muss sich von der Domain in server_url unterscheiden (Schritt 3).
  • Subnet-Router funktioniert nach Neustart nicht mehr: IP-Forwarding in /etc/sysctl.d/99-tailscale.conf speichern (Schritt 8).
  • Exit-Node wird von macOS/iOS nicht angeboten: In Versionen vor 0.29.4 ein bekannter Fehler; auf die aktuelle Patch-Version aktualisieren.
  • Headscale und Tailscale-Client auf demselben Host: Nicht unterstützt (Konflikte bei Subnet-Routing, MagicDNS, Relay); getrennte Hosts verwenden.
  • PostgreSQL geplant: Headscale führt PostgreSQL nur noch im „maintenance mode“. Neue Instanzen mit SQLite (Standard) aufsetzen.
  • Befehl unbekannt nach Update (headscale routes, policy apply): Diese Befehle gibt es nicht mehr; Routen verwalten Sie mit headscale nodes list-routes und approve-routes. Keine Minor-Version überspringen (z. B. 0.27 → 0.28 → 0.29).
  • Keine Verbindung hinter doppeltem NAT: Eingebetteten DERP-Server aktivieren (derp.server.enabled: true) und UDP/3478 freigeben oder eine eigene derper-Instanz betreiben.

Häufige Fragen

Kann ich die offiziellen Tailscale-Apps mit Headscale nutzen?

Ja, auf allen Plattformen, ab Tailscale-Client 1.80 (Login-Server siehe Schritt 6).

Wie groß muss der Server für Headscale sein?

1 vCPU, 1 bis 2 GB RAM und 20 GB SSD; der Control Server liegt nicht im Datenpfad.

Was passiert, wenn mein Headscale-Server ausfällt?

Bestehende Verbindungen bleiben aktiv, solange die WireGuard-Sessions laufen; neue Verbindungen scheitern bis zur Rückkehr des Servers. Ein Backup von /var/lib/headscale/ (SQLite-Datenbank, Private Keys) ist Pflicht, z. B. per Restic-Backup unter Linux und Windows automatisieren.

Brauche ich einen eigenen DERP-Server für vollständige DSGVO-Konformität?

Nicht zwingend. Über die Standard-DERP-Map weitergeleitete Inhalte bleiben Ende-zu-Ende verschlüsselt. Für vollständige Datenlokalisierung siehe Schritt 10.

Wie vergleicht sich die Performance gegenüber reinem WireGuard?

Nein, Headscale liegt nicht im Datenpfad. Die Clients nutzen wireguard-go im Userspace, auf aktuellem Linux dennoch nah an Kernel-WireGuard. Über DERP-Relays begrenzen Relay-Bandbreite und Latenz.

Wann sollte ich lieber bei Tailscale-Cloud bleiben?

Wenn schnelles Onboarding wichtiger ist als Datensouveränität, das IT-Team sehr klein ist oder SSO (Google, Microsoft Entra ID) ohne eigenen OIDC-Dienst nötig ist (siehe Schritt 1).

Was bedeutet „Key-Expiry“ in Headscale konkret?

Node-Keys laufen per Default nie ab, Pre-Auth-Keys nach einer Stunde. Details und die Option node.expiry beschreibt Schritt 10.

Fazit

Headscale liegt zwischen manuell verwaltetem WireGuard und Tailscale-Cloud. Rechnen Sie mit etwa 90 Minuten Einrichtung und planen Sie Updates bewusst, da sich CLI und Konfiguration zwischen Minor-Versionen ändern.

Weiterführende Anleitungen und Quellen

Quellen: Headscale auf GitHub (Changelog und Beispielkonfiguration), Headscale-Dokumentation (Installation, Routen, Policy, Reverse Proxy, FAQ).