VPNSmith
Kostenloses Tool - Headscale-Server

Headscale Config Generator

Gib deine Domain ein, wähle Docker oder das .deb-Paket und wie HTTPS bereitgestellt wird: Der Generator schreibt config.yaml, die Compose-Datei oder das Installationsskript, die Reverse-Proxy-Datei, eine optionale Exit-Node-Policy und die Befehle für den ersten Benutzer und das erste Gerät. Aufgebaut auf den offiziellen Dateien von Headscale 0.29.5. Nichts verlässt deinen Browser.

Alles wird in deinem Browser erzeugt. Nichts wird gesendet oder gespeichert.

Ein DNS-Name, dessen A- (und AAAA-) Eintrag auf den VPS zeigt, zum Beispiel headscale.example.com.

Geräte heißen dann name.basisdomain. Muss sich von der Domain oben unterscheiden; sie muss nicht öffentlich existieren.

Wird mit headscale users create angelegt. Dient auch als Tag-Owner in der Exit-Node-Policy.

Von certbot oder Headscale für Ablaufhinweise genutzt. Caddy funktioniert ohne.

Installationsart
HTTPS

Caddy ist der kürzeste Weg. Nimm nginx, wenn es schon auf dem Server läuft, eingebautes TLS, wenn auf dem VPS nur Headscale läuft.

Upstream-DNS für MagicDNS
Optionen
  • Lege den DNS-Eintrag der Domain vor dem Start an: Die Zertifikatsanfrage scheitert, solange der Name nicht auf den VPS zeigt.

Erzeugt für https://headscale.example.com · Headscale 0.29.5 · 6 Dateien

/opt/headscale/config/config.yaml
---
# Headscale 0.29.5: /etc/headscale/config.yaml
server_url: https://headscale.example.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090
grpc_listen_addr: 127.0.0.1:50443
grpc_allow_insecure: false
trusted_proxies: []
noise:
  private_key_path: /var/lib/headscale/noise_private.key
prefixes:
  v4: 100.64.0.0/10
  v6: fd7a:115c:a1e0::/48
  allocation: sequential
derp:
  server:
    enabled: false
    region_id: 999
    region_code: "headscale"
    region_name: "Headscale Embedded DERP"
    verify_clients: true
    stun_listen_addr: "0.0.0.0:3478"
    private_key_path: /var/lib/headscale/derp_server_private.key
    automatically_add_embedded_derp_region: true
  urls:
    - https://controlplane.tailscale.com/derpmap/default
  paths: []
  auto_update_enabled: true
  update_frequency: 3h
disable_check_updates: false
node:
  expiry: 0
  ephemeral:
    inactivity_timeout: 30m
database:
  type: sqlite
  sqlite:
    path: /var/lib/headscale/db.sqlite
    write_ahead_log: true
    wal_autocheckpoint: 1000
acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""
tls_letsencrypt_hostname: ""
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
tls_letsencrypt_challenge_type: HTTP-01
tls_letsencrypt_listen: ":http"
tls_cert_path: ""
tls_key_path: ""
log:
  level: info
  format: text
policy:
  mode: file
  path: "/etc/headscale/policy.json"
dns:
  magic_dns: true
  base_domain: ts.example.com
  override_local_dns: true
  nameservers:
    global:
      - 1.1.1.1
      - 1.0.0.1
      - 2606:4700:4700::1111
      - 2606:4700:4700::1001
    split: {}
  search_domains: []
  extra_records: []
unix_socket: /var/run/headscale/headscale.sock
unix_socket_permission: "0770"
logtail:
  enabled: false
taildrop:
  enabled: true
/opt/headscale/docker-compose.yaml
services:
  headscale:
    image: docker.io/headscale/headscale:0.29.5
    container_name: headscale
    restart: unless-stopped
    read_only: true
    tmpfs:
      - /var/run/headscale
    ports:
      - "127.0.0.1:8080:8080"
      - "127.0.0.1:9090:9090"
    volumes:
      - /opt/headscale/config:/etc/headscale:ro
      - /opt/headscale/lib:/var/lib/headscale
    command: serve
    healthcheck:
      test: ["CMD", "headscale", "health"]

  caddy:
    image: docker.io/library/caddy:2
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - /opt/headscale/Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - headscale

volumes:
  caddy_data:
  caddy_config:
/opt/headscale/Caddyfile
http://headscale.example.com {
	# Tailscale captive portal detection
	handle /generate_204 {
		respond 204
	}

	handle * {
		redir https://{host}{uri}
	}
}

headscale.example.com {
	reverse_proxy headscale:8080 {
		header_up True-Client-IP {remote_host}
		header_up X-Real-IP {remote_host}
	}
}
/opt/headscale/config/policy.json
{
  "tagOwners": {
    "tag:exit": [
      "admin@"
    ]
  },
  "autoApprovers": {
    "exitNode": [
      "tag:exit"
    ]
  }
}
setup-headscale.sh
#!/usr/bin/env bash
set -euo pipefail

# 1. Docker installieren, falls nicht vorhanden (offizielles Skript)
command -v docker >/dev/null || curl -fsSL https://get.docker.com | sudo sh

# 2. Ordner für Konfiguration und Daten
sudo mkdir -p /opt/headscale/config /opt/headscale/lib
cd /opt/headscale

# 3. Zuerst die erzeugten Dateien unter diesen Pfaden speichern
for f in config/config.yaml docker-compose.yaml Caddyfile config/policy.json; do
  [ -f "$f" ] || { echo "Missing /opt/headscale/$f"; exit 1; }
done

# 4. Headscale starten
sudo docker compose up -d
sleep 5

# 5. Prüfung: muss einen JSON-Gesundheitsstatus ausgeben
curl -fsS http://127.0.0.1:8080/health
first-steps.sh
# Ersten Benutzer anlegen
sudo docker exec headscale headscale users create admin

# Numerische ID des Benutzers notieren
sudo docker exec headscale headscale users list

# Pre-Auth-Key erstellen (1 Stunde gültig, standardmäßig einmal nutzbar)
sudo docker exec headscale headscale preauthkeys create --user <USER_ID>

# Auf jedem Gerät: beim eigenen Headscale-Server anmelden
sudo tailscale up --login-server https://headscale.example.com --authkey <YOUR_AUTH_KEY>

# Auf dem Exit-Node-VPS: mit dem Tag anmelden, damit er automatisch freigegeben wird
sudo tailscale up --login-server https://headscale.example.com --authkey <YOUR_AUTH_KEY> \
  --advertise-exit-node --advertise-tags=tag:exit

# Nach Änderungen an policy.json: Headscale neu laden
sudo docker kill --signal=HUP headscale

# Stattdessen Anmeldung im Browser: Gerät mit der angezeigten Auth-ID freigeben
sudo docker exec headscale headscale auth register --user admin --auth-id <AUTH_ID>

# Verbundene Geräte auflisten
sudo docker exec headscale headscale nodes list

Headscale braucht einen Server, der immer läuft

Ein kleiner VPS mit öffentlicher IPv4 und IPv6 führt diese Dateien unverändert aus, und dieselbe Maschine kann der Exit Node deines Tailnets sein.

Affiliate-Link: Wir erhalten eventuell eine Provision, ohne Mehrkosten für dich. Der Generator bleibt kostenlos und hängt nicht davon ab.

Zum VPS von Contabo

Was die erzeugten Dateien tun

Headscale ist der Open-Source-Ersatz für den Steuerungsserver von Tailscale: Deine Geräte behalten die offiziellen Tailscale-Apps, melden sich aber mit --login-server bei deinem eigenen Server an. Dafür braucht es drei Dinge: eine öffentliche HTTPS-Adresse auf Port 443, die server_url entspricht, eine MagicDNS-base_domain, die sich von dieser Adresse unterscheidet, und einen Reverse Proxy, der WebSocket-Upgrades durchlässt, falls Headscale TLS nicht selbst übernimmt.

Die config.yaml ist die vollständige Beispieldatei der Version 0.29.5 mit deinen Werten: Alle Schlüssel sind vorhanden, nichts hängt von einem undokumentierten Standardwert ab. Unter Docker lauscht der Container in seinem eigenen Netz auf 0.0.0.0, veröffentlicht werden die Ports nur auf 127.0.0.1, außer 80 und 443, wenn Headscale TLS terminiert. Hinter einem Reverse Proxy auf demselben Host steht trusted_proxies auf localhost, damit die echten Client-IPs in den Logs erscheinen.

Mehrere Befehle haben sich in den letzten Versionen geändert, deshalb scheitern viele Anleitungen: Pre-Auth-Keys werden jetzt mit der numerischen Benutzer-ID erstellt (headscale users list zeigt sie), und ein Gerät, das sich über den Browser anmeldet, wird mit headscale auth register und seiner Auth-ID freigegeben. Der Block mit den ersten Schritten nutzt die Syntax von 0.29.

Caddy, nginx oder eingebautes TLS?

Drei Wege, Headscale per HTTPS auszuliefern, alle vom Projekt dokumentiert. Die richtige Wahl hängt davon ab, was sonst auf dem Server läuft.

HTTPS überZertifikatIdeal, wennAchtung
Caddy (Reverse Proxy)Automatisch, von Caddy erneuertDu das kürzeste Setup willst oder weitere Seiten auf demselben VPS laufenPorts 80 und 443 müssen bei Caddy ankommen; WebSocket klappt ohne Zusatzzeile
nginx (Reverse Proxy)certbot, per Timer erneuertnginx bereits andere Seiten auf dem Server ausliefertDie Header Upgrade und Connection sind Pflicht, sonst verbinden sich die Clients nie
Let's Encrypt in HeadscaleAutomatisch, von Headscale erneuertAuf dem VPS nur Headscale läuftHeadscale belegt Port 80 und 443 selbst; kein anderer Webdienst auf dieser IP

Häufige Fragen

Wie sieht die minimale config.yaml für Headscale aus?
Headscale liest /etc/headscale/config.yaml. Ändern musst du server_url (deine öffentliche HTTPS-Adresse), listen_addr und dns.base_domain, das eine andere Domain als server_url sein muss. Am sichersten startest du mit der Beispieldatei genau deiner Version und diesen geänderten Werten, und genau das erzeugt dieser Generator, denn Schlüssel werden zwischen Versionen umbenannt.
Warum hängt oder scheitert tailscale up mit meinem Headscale-Server?
Meist reicht der Reverse Proxy das WebSocket-Upgrade nicht durch (nginx ohne die Header Upgrade und Connection), server_url passt nicht zur Adresse der Clients, oder dem Zertifikat wird nicht vertraut. Teste curl https://deine-domain/health von außerhalb des Servers und lies dann die Headscale-Logs. Ein anderer Port als 443 ist möglich, doch der Tailscale-Client setzt in manchen Fällen 443 voraus.
Wie erstelle ich einen Pre-Auth-Key in Headscale 0.29?
Lege mit headscale users create <name> einen Benutzer an, lies mit headscale users list seine numerische ID ab und führe headscale preauthkeys create --user <ID> aus. Standardmäßig gilt der Key eine Stunde und ist einmal verwendbar. Auf dem Gerät: tailscale up --login-server https://deine-domain --authkey <key>.
Brauche ich den eingebetteten DERP-Server?
Nein. Standardmäßig gibt Headscale den Clients die öffentlichen DERP-Relays von Tailscale, die nur genutzt werden, wenn keine direkte Verbindung möglich ist. Aktiviere den eingebetteten DERP, wenn du Relays unter eigener Kontrolle willst: Dafür muss UDP 3478 offen sein und die öffentliche IPv4 (und gegebenenfalls IPv6) des Servers in der Konfiguration stehen.
Wie groß muss der VPS für Headscale sein?
Sehr klein: Der Steuerungsserver koordiniert nur Schlüssel und Routen, der Verkehr läuft direkt zwischen den Geräten. Die kleinsten Tarife reichen für einen Haushalt oder ein kleines Team. Wichtig sind eine öffentliche IPv4, idealerweise auch IPv6, und ein Anbieter, der die Ports 80, 443 und 3478 offen lässt. Derselbe Server kann auch dein Exit Node sein.