Headscale: das eigene Tailscale-Netz
Headscale 0.29.5 als eigener Control-Server hinter Traefik: Knoten verbinden, MagicDNS, eigener DERP-Relay, ACLs und Exit-Node – ohne fremde Cloud.
Inhaltsverzeichnis
WireGuard ist großartig, bis du das fünfte Gerät einträgst: Jeder Peer braucht jeden anderen Schlüssel, jede neue IP muss überall nachgepflegt werden, und hinter zwei NATs kommt trotzdem keine Verbindung zustande. Genau das löst Tailscale – und Headscale löst es, ohne dass deine Geräteliste bei einem fremden Anbieter liegt.
Was bauen wir?
Wir betreiben Headscale 0.29.5 als eigenen Control-Server hinter Traefik. Daran hängen zwei Knoten mit dem offiziellen Tailscale-Client 1.104.1, die sich über MagicDNS beim Namen ansprechen. Der Relay-Server (DERP) läuft eingebettet im selben Container, eine ACL-Datei regelt, wer wen erreichen darf, und zum Schluss dient der Server als Exit-Node.
Wichtig für das Verständnis: Headscale ist nur die Steuerebene. Es verteilt öffentliche Schlüssel, IP-Adressen und Regeln. Der eigentliche Datenverkehr läuft danach als direkte WireGuard-Verbindung zwischen den Geräten – am Server vorbei. Fällt Headscale aus, reden bestehende Knoten weiter miteinander; nur neue Geräte und Regeländerungen brauchen es.
Der Unterschied zu einem klassischen WireGuard-Setup ist damit: dort ein Stern mit dem Server in der Mitte und Handarbeit pro Peer, hier ein Mesh, in dem sich Geräte selbst finden und auch hinter NAT direkt verbinden.
Voraussetzungen
- Ein Server mit Traefik als Reverse Proxy und einer Domain, die darauf zeigt – Headscale muss über HTTPS erreichbar sein
- WireGuard-Grundlagen: Du solltest wissen, was ein Peer, ein öffentlicher Schlüssel und ein AllowedIP ist
- Vertrautheit mit Docker Compose
- Ein zweites Gerät (Laptop, zweiter Server, Handy), das dem Netz beitreten kann
VPS 1000 G12.5
4 vCore · 8 GB RAM · 128 GB SSD
ab 14,50 €/Monat
Headscale selbst ist genügsam – ein VPS 1000 reicht für Steuerebene und Relay.
💶 1 Monat gratis:
Einmal einlösbar, gilt für VPS 1000 G12.5. Im Warenkorb einlösen →
💶 5,95 € Gutschein für netcup-Neukunden: immer gültig · nicht für Domains und VPS Lite
Schritt für Schritt
Schritt 1: Die Konfiguration schreiben
Headscale wird über eine einzige YAML-Datei konfiguriert. Leg die Ordner an:
mkdir -p /opt/headscale/config /opt/headscale/data && cd /opt/headscaleDie Konfiguration ist der Teil, an dem die meisten Setups scheitern – deshalb hier in Blöcken mit
Begründung. Ersetze DEINE_DOMAIN durch die Domain, unter der Headscale erreichbar sein soll, und
DEINE_SERVER_IP durch die öffentliche IPv4 deines Servers.
# /opt/headscale/config/config.yaml
server_url: https://DEINE_DOMAIN
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
grpc_allow_insecure: false
noise:
private_key_path: /var/lib/headscale/noise_private.key
trusted_proxies:
- 172.19.0.0/16server_url ist die Adresse, die alle Clients später benutzen – sie steht in jedem
tailscale up-Aufruf und lässt sich nachträglich nur mit Schmerzen ändern. listen_addr bindet auf
alle Interfaces des Containers, damit Traefik drankommt; nach außen ist trotzdem nur Traefik
erreichbar.
noise.private_key_path ist Pflicht: Ohne den Eintrag startet Headscale nicht und meldet
headscale now requires a new noise.private_key_path field in the config file for the Tailscale v2 protocol. Den Schlüssel selbst legt Headscale beim ersten Start an.
trusted_proxies ist der Eintrag, den man gern vergisst: Ohne ihn ignoriert Headscale die
X-Forwarded-For-Header und protokolliert jede Anmeldung mit der IP von Traefik. Trag das Subnetz
deines Docker-Proxy-Netzes ein – docker network inspect proxy --format '{{ range .IPAM.Config }}{{ .Subnet }}{{ end }}'
zeigt es dir.
Achtung
trusted_proxies nur, wenn wirklich ein Proxy davor steht. Ohne Proxy erlaubst du damit
jedem Client, seine eigene Quell-IP im Protokoll zu fälschen.Weiter mit den Adressbereichen und dem Relay:
prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
allocation: sequential
derp:
server:
enabled: true
region_id: 999
region_code: "kueche"
region_name: "Eigener DERP"
verify_clients: false
stun_listen_addr: "0.0.0.0:3478"
private_key_path: /var/lib/headscale/derp_server_private.key
automatically_add_embedded_derp_region: true
ipv4: DEINE_SERVER_IP
urls: []
paths: []
auto_update_enabled: false
update_frequency: 24hDie Präfixe müssen innerhalb von 100.64.0.0/10 bzw. fd7a:115c:a1e0::/48 liegen – der
Tailscale-Client hat diese Bereiche fest verdrahtet und bricht bei anderen Werten auf subtile Weise.
DERP ist Tailscales Relay: Wenn zwei Geräte partout keine direkte Verbindung aufbauen können
(symmetrisches NAT, restriktive Firewalls), läuft der Verkehr verschlüsselt über einen Relay-Server.
Standardmäßig sind das die Server von Tailscale Inc. Mit enabled: true betreibst du deinen eigenen
und setzt urls: [], damit die fremde Liste gar nicht erst geladen wird – dann verlässt kein Byte
deines Netzes die eigene Infrastruktur. verify_clients: false ist nötig, weil die Prüfung einen
lokalen tailscaled-Socket voraussetzt, den es im Container nicht gibt.
Zum Schluss Datenbank, Regeln und DNS:
disable_check_updates: true
node:
expiry: 0
database:
type: sqlite
sqlite:
path: /var/lib/headscale/db.sqlite
write_ahead_log: true
log:
level: info
format: text
policy:
mode: file
path: /etc/headscale/policy.json
dns:
magic_dns: true
base_domain: kueche.internal
override_local_dns: true
nameservers:
global:
- 9.9.9.9
- 149.112.112.112Die Policy-Datei aus policy.path muss beim Start existieren, sonst bricht Headscale mit
loading policy: open /etc/headscale/policy.json: no such file or directory ab. Bis du in Schritt 7
echte Regeln schreibst, legst du /opt/headscale/config/policy.json mit diesem Inhalt an – er
erlaubt alles:
{
"acls": [
{ "action": "accept", "src": ["*"], "dst": ["*:*"] }
]
}SQLite ist hier kein Kompromiss, sondern die empfohlene Wahl – die Headscale-Entwickler entwickeln und testen gegen SQLite, Postgres wird nur aus Altlastgründen weiter unterstützt.
base_domain darf nicht zur server_url passen
base_domain ist die Zone für MagicDNS und muss eine andere Domain sein als die in server_url.
Sonst startet Headscale gar nicht erst und meldet:
server_url cannot use the same domain as base_domain in a way that could make the DERP and headscale server unreachable.
Nimm etwas rein internes wie kueche.internal.Schritt 2: Den Stack starten
# /opt/headscale/compose.yaml
services:
headscale:
image: ghcr.io/juanfont/headscale:v0.29.5
container_name: headscale
restart: unless-stopped
command: serve
volumes:
- ./config:/etc/headscale
- ./data:/var/lib/headscale
ports:
- "3478:3478/udp"
networks: [proxy]
labels:
- traefik.enable=true
- traefik.http.routers.headscale.rule=Host(`DEINE_DOMAIN`)
- traefik.http.routers.headscale.entrypoints=websecure
- traefik.http.routers.headscale.tls.certresolver=le
- traefik.http.services.headscale.loadbalancer.server.port=8080
networks:
proxy:
external: trueDer Image-Tag ist bewusst auf v0.29.5 festgenagelt. Headscale ist vor 1.0 und ändert zwischen
Minor-Versionen durchaus Konfigurationsformate – latest ist hier eine schlechte Idee.
Der einzige direkt veröffentlichte Port ist UDP 3478 für STUN. Das braucht der DERP-Server, um Clients bei der NAT-Durchdringung zu helfen; HTTPS und der DERP-Kanal selbst laufen über Traefik. Wenn du UFW einsetzt, muss 3478/udp offen sein – und hast du in der netcup-Firewall eine Policy zugewiesen, braucht sie dort ebenfalls eine eingehende Regel für UDP 3478. Fehlt sie, funktioniert das Netz trotzdem, aber jede Verbindung läuft über den Relay statt direkt (siehe Schritt 6).
docker compose up -d
docker compose logs --tail 20In den Logs solltest du das hier sehen:
INF no private key file at path, creating... path=/var/lib/headscale/noise_private.key
INF Opening database database=sqlite3 path=/var/lib/headscale/db.sqlite
INF no private key file at path, creating... path=/var/lib/headscale/derp_server_private.key
INF starting headscale commit=0f7d1e536bed9f01dd7161f7637af19bb0908335 version=v0.29.5
INF Clients with a lower minimum version will be rejected minimum_version=v1.80
INF stun server started at [::]:3478
WRN listening without TLS but ServerURL does not start with http://
INF listening and serving HTTP on: 0.0.0.0:8080Die Warnung in der vorletzten Zeile ist korrekt und erwartet: Headscale spricht intern HTTP, das TLS macht Traefik. Merk dir außerdem die Zeile darüber – Clients älter als 1.80 werden abgewiesen.
Prüf jetzt von außen, ob die Kette steht:
curl https://DEINE_DOMAIN/health{"status":"pass"}Kommt hier ein Zertifikatsfehler oder ein 404, ist das ein Traefik-Problem und keins von Headscale – weiter unten steht, wie du das auseinanderhältst.
Schritt 3: Benutzer und Anmeldeschlüssel
Headscale ordnet jeden Knoten einem Benutzer zu. Ein Benutzer reicht für ein Privatnetz:
docker compose exec headscale headscale users create kueche
docker compose exec headscale headscale users listID | Name | Username | Email | Created
1 | | kueche | | 2026-09-10 02:20:44Neue Geräte melden sich mit einem Pre-Auth-Key an. Der --user erwartet die ID aus der
Liste, nicht den Namen:
docker compose exec headscale headscale preauthkeys create --user 1 --reusable --expiration 1hhskey-auth-XXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXVorsicht
--expiration 1h), verschick ihn nicht über Chat oder Mail, und lass
--reusable weg, wenn du nur ein einziges Gerät verbindest. Nach dem Anlegen bekommst du ihn nur
dieses eine Mal vollständig zu sehen – preauthkeys list zeigt später nur noch das Präfix.Schritt 4: Den ersten Knoten verbinden
Auf dem Gerät, das beitreten soll, installierst du den offiziellen Tailscale-Client. Der Schlüssel
kommt als binäre Datei, deshalb braucht es kein gnupg:
curl -fsSL https://pkgs.tailscale.com/stable/debian/trixie.noarmor.gpg \
-o /usr/share/keyrings/tailscale-archive-keyring.gpg
curl -fsSL https://pkgs.tailscale.com/stable/debian/trixie.tailscale-keyring.list \
-o /etc/apt/sources.list.d/tailscale.list
chmod 0644 /usr/share/keyrings/tailscale-archive-keyring.gpg /etc/apt/sources.list.d/tailscale.listDas chmod sieht überflüssig aus, ist es aber nicht: Auf gehärteten Systemen mit UMASK 027 legt
curl die Dateien mit 0640 an, und apt kann sie dann nicht mehr lesen. Details dazu unten bei
„Wenn es nicht funktioniert".
apt-get update
apt-get install -y tailscale
tailscale version1.104.1Jetzt der Beitritt. Der entscheidende Schalter ist --login-server, der den Client auf deinen
Headscale statt auf Tailscales Cloud zeigt:
tailscale up \
--login-server=https://DEINE_DOMAIN \
--authkey=DEIN_PREAUTH_KEY \
--accept-dns=false \
--hostname=kueche-server--accept-dns=false ist auf Servern wichtig: Sonst schreibt tailscaled die /etc/resolv.conf
um und leitet die Namensauflösung über das VPN. Auf einem Server, der weiterlaufen muss, ist das
selten gewollt. Auf Laptops und Handys lässt du die Option weg – dort willst du MagicDNS ja gerade.
tailscale ip -4100.64.0.1Schritt 5: Zweiter Knoten und MagicDNS
Der zweite Knoten wird genauso installiert, nur mit anderem Hostnamen und ohne
--accept-dns=false:
tailscale up \
--login-server=https://DEINE_DOMAIN \
--authkey=DEIN_PREAUTH_KEY \
--hostname=laptopAuf dem Server siehst du beide Knoten:
docker compose exec headscale headscale nodes listID | Hostname | Name | MachineKey | NodeKey | User | Tags | IP addresses | Ephemeral | Last seen | Expiration | Connected | Expired
1 | kueche-server | kueche-server | [k54+k] | [71w+9] | kueche | | 100.64.0.1 | false | 2026-10-11 19:55:56 | N/A | online | no
| | | | | | | fd7a:115c:a1e0::1 | | | | |
2 | laptop | laptop | [QqjtX] | [7F2yB] | kueche | | 100.64.0.2 | false | 2026-10-11 19:56:34 | N/A | online | no
| | | | | | | fd7a:115c:a1e0::2 | | | | |Auf dem Laptop hat tailscaled inzwischen den DNS-Resolver umgebogen:
cat /etc/resolv.conf# resolv.conf(5) file generated by tailscale
nameserver 100.100.100.100
nameserver fd7a:115c:a1e0::53
search kueche.internal100.100.100.100 ist der eingebaute MagicDNS-Resolver. Damit klappt jetzt das, wofür man das Ganze
eigentlich macht:
ping -c 2 kueche-server2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.728/0.764/0.800/0.036 msDer kurze Name reicht, kueche-server.kueche.internal funktioniert genauso. Ob die Verbindung
wirklich direkt läuft oder über den Relay geht, sagt dir tailscale ping:
tailscale ping kueche-serverpong from kueche-server (100.64.0.1) via 172.19.0.1:41641 in 0sKommt keine direkte Verbindung zustande, arbeitet der Relay, und alles funktioniert weiter, nur mit etwas mehr Latenz. Dann sieht es so aus:
pong from kueche-server (100.64.0.1) via DERP(kueche) in 1ms
direct connection not establishedDer häufigste Grund auf einem netcup-Server ist eine Firewall-Policy im SCP, die eingehendes UDP sperrt.
Schritt 6: Prüfen, dass der eigene Relay benutzt wird
Der Sinn des eingebetteten DERP-Servers ist, dass im Ernstfall nicht Tailscales Infrastruktur einspringt. Ob das greift, zeigt der Client:
tailscale netcheck* Nearest DERP: Eigener DERP
* DERP latency:
- kueche: 400µs (Eigener DERP)Nur eine Region, und zwar deine. Steht weiter oben in der Ausgabe UDP: false, erreicht der Client
deinen STUN-Port nicht – der Fall aus Schritt 2, in dem die netcup-Firewall UDP 3478 nicht
durchlässt. Erscheint hier eine Liste mit fra, ams oder ähnlichen Codes,
hat der Client die öffentliche DERP-Liste geladen – dann fehlt urls: [] in der Konfiguration.
Schritt 7: ACLs – wer darf mit wem
Bisher erlaubt deine Policy-Datei aus Schritt 1 jedem Knoten alles. Sobald echte Regeln darin
stehen, gilt Default-Deny: Was nicht ausdrücklich erlaubt ist, wird verworfen. Eine minimale,
sinnvolle Regel – sie ersetzt den Inhalt von /opt/headscale/config/policy.json:
{
"groups": {
"group:haushalt": ["kueche@"]
},
"acls": [
{
"action": "accept",
"src": ["group:haushalt"],
"dst": ["group:haushalt:22,80,443"]
},
{
"action": "accept",
"src": ["group:haushalt"],
"dst": ["autogroup:internet:*"]
}
]
}Beachte das @ hinter dem Benutzernamen – seit dem Policy-Format v2 ist es Pflicht. Prüf die Datei,
bevor du neu startest:
docker compose exec headscale headscale policy check --file /etc/headscale/policy.jsonPolicy is validdocker compose restart headscaleUnd jetzt gegenprüfen, dass die Regel wirklich greift. Port 443 ist erlaubt, 9090 nicht. Damit die Probe etwas beweist, muss auf 9090 aber auch etwas lauschen – sonst meldet sie „BLOCKIERT“ schon, weil dort niemand antwortet. Starte auf dem Server kurz einen Testdienst:
python3 -m http.server 9090 --bind 100.64.0.1Und prüf dann vom Laptop aus:
timeout 5 bash -c "</dev/tcp/100.64.0.1/443" && echo OFFEN || echo BLOCKIERT
timeout 5 bash -c "</dev/tcp/100.64.0.1/9090" && echo OFFEN || echo BLOCKIERTOFFEN
BLOCKIERTMit der Alles-erlauben-Datei aus Schritt 1 stünde in der zweiten Zeile OFFEN – so weißt du, dass
die Regel den Unterschied macht. Den Testdienst beendest du danach mit Strg+C.
ICMP folgt der Portregel nicht
ping auf 100.64.0.1 klappt trotzdem, obwohl in der Regel nur 22, 80 und 443 stehen. Das ist
kein Fehler: Der Tailscale-Paketfilter lässt ICMP zu, sobald die Quelle irgendeinen Port am Ziel
erreichen darf. Nimm die Gegenprobe – entfernst du das Ziel komplett aus den Regeln, ist auch der
Ping weg (2 packets transmitted, 0 received). Ein erfolgreicher Ping beweist also nur, dass
überhaupt eine Regel greift, nicht welche.Schritt 8: Der Server als Exit-Node
Ein Exit-Node schickt den kompletten Internetverkehr eines Geräts über den Server – praktisch im fremden WLAN. Anbieten muss ihn der Server:
tailscale set --advertise-exit-nodeAngeboten heißt noch nicht erlaubt. Auf dem Headscale-Server musst du die Route freigeben:
docker compose exec headscale headscale nodes list-routes
docker compose exec headscale headscale nodes approve-routes --identifier 1 --routes "0.0.0.0/0,::/0"ID | Hostname | Approved | Available | Serving (Primary)
1 | kueche-server | 0.0.0.0/0 | 0.0.0.0/0 | 0.0.0.0/0
| | ::/0 | ::/0 | ::/0Auf dem Client einschalten:
tailscale set --exit-node=kueche-serverAm einfachsten prüfst du das an der öffentlichen IP, mit der der Client jetzt im Internet auftaucht – sie muss die deines Servers sein:
curl -4 -s https://ifconfig.meDahinter steckt die Routing-Tabelle 52, die Tailscale per Policy-Routing vor die normale Tabelle hängt:
ip route show table 52default dev tailscale0
100.64.0.1 dev tailscale0
100.100.100.100 dev tailscale0Abschalten geht mit tailscale set --exit-node= ohne Wert.
Subnetz-Routen funktionieren nach demselben Muster: Der Server wirbt mit
tailscale set --advertise-routes=192.168.178.0/24 für ein ganzes LAN, du gibst es mit
approve-routes frei, und die Clients holen es sich mit tailscale set --accept-routes. Ohne
--accept-routes liegt die Route zwar bereit, wird aber nicht installiert – das ist der häufigste
Grund, warum „die Route ist doch approved" trotzdem nicht funktioniert.
Wenn es nicht funktioniert
Headscale startet nicht und meldet headscale now requires a new noise.private_key_path field. In der config.yaml fehlt der Block noise: mit private_key_path: /var/lib/headscale/noise_private.key (Schritt 1). Den Schlüssel selbst musst du nicht anlegen, das erledigt Headscale beim Start.
Headscale startet in einer Schleife neu, im Log steht loading policy: open /etc/headscale/policy.json: no such file or directory. policy.path zeigt auf eine Datei, die es noch nicht gibt. Leg die Alles-erlauben-Datei aus Schritt 1 an oder gleich deine echten Regeln aus Schritt 7.
apt-get update meldet The repository 'https://pkgs.tailscale.com/...' is not signed. Schau in die Zeile darüber, dort steht meist Failed to parse keyring ... Permission denied (os error 13). Ursache ist eine strengere UMASK (etwa 027) auf dem System: curl -o legt den Schlüssel dann mit Modus 0640 an, und apt prüft Signaturen als unprivilegierter Benutzer _apt, der die Datei nicht lesen darf. chmod 0644 /usr/share/keyrings/tailscale-archive-keyring.gpg /etc/apt/sources.list.d/tailscale.list behebt es sofort.
Headscale startet nicht und meldet server_url cannot use the same domain as base_domain. dns.base_domain und die Domain in server_url überschneiden sich. Headscale verweigert das, weil sonst der eigene Control-Server über MagicDNS aufgelöst würde und sich damit selbst unerreichbar machen könnte. Wähl für base_domain eine eigene, nicht öffentliche Zone wie kueche.internal und prüf die Datei vor jedem Neustart mit docker compose exec headscale headscale configtest.
In den Logs steht listening without TLS but ServerURL does not start with http://. Das ist keine Fehlfunktion, sondern der Normalzustand hinter einem Reverse Proxy: Headscale selbst spricht HTTP, Traefik macht das TLS. Ein echtes Problem erkennst du daran, dass curl https://DEINE_DOMAIN/health nicht {"status":"pass"} liefert – dann liegt es an Traefik, nicht an Headscale.
Ein Client verbindet sich nicht und bleibt bei der Anmeldung hängen. Prüf zuerst die Clientversion mit tailscale version: Headscale 0.29 weist alles unterhalb von 1.80 ab, und die Distributionspakete mancher LTS-Systeme liegen darunter. Steht die Version, ist der nächste Verdächtige der Pre-Auth-Key – Standardlaufzeit ist eine Stunde, und preauthkeys list zeigt dir in der Spalte Expiration, ob er noch gilt.
Eine Subnetz-Route ist freigegeben und im Client installiert, das Ziel bleibt trotzdem unerreichbar. Wenn das Zielnetz ein Docker-Netzwerk auf demselben Host ist, blockiert Docker den Verkehr selbst. In der Filterkette steht -A DOCKER ! -i br-XXXX -o br-XXXX -j DROP, und Pakete, die über tailscale0 hereinkommen, fallen genau darauf. Für Container-Netze nimmst du deshalb keine Subnetz-Route, sondern veröffentlichst den Dienst regulär über den Reverse Proxy. Bei echten LANs prüfst du stattdessen, ob auf dem Subnetz-Router net.ipv4.ip_forward=1 gesetzt ist.
Dein Problem ist nicht dabei? Alle Fehlermeldungen durchsuchen →
Wartung & Backups
Updates sind bei Headscale kein Selbstläufer. Das Projekt steht vor 1.0, und zwischen Minor-Versionen ändern sich Konfigurationsschlüssel und das Policy-Format. Lies vor jedem Sprung die Release Notes, insbesondere die Zeile zur minimalen Clientversion, und geh so vor:
cd /opt/headscale
cp -a data data-backup-$(date +%F)
sed -i 's/headscale:v0.29.5/headscale:vNEUE_VERSION/' compose.yaml
docker compose pull && docker compose up -d
docker compose exec headscale headscale configtestDie Datenbankmigration läuft beim Start automatisch – deshalb die Kopie vorher. Der Tailscale-Client auf den Knoten aktualisiert sich dagegen über apt und darf ruhig vorauslaufen.
Sichern musst du drei Dinge, und zwei davon sind unersetzlich:
/opt/headscale/data/db.sqlite # Knoten, Benutzer, Routen
/opt/headscale/data/noise_private.key # ohne den kennt dich kein Client wieder
/opt/headscale/data/derp_server_private.key
/opt/headscale/config/ # config.yaml + policy.jsonVerlierst du noise_private.key, müssen sich alle Geräte neu anmelden. Nimm den Ordner in dein
Restic-Backup auf. Weil SQLite mit aktiviertem Write-Ahead-Log in
mehreren Dateien liegt, hältst du den Container für die Sicherung kurz an – docker compose stop,
sichern, docker compose start. Das kostet ein paar Sekunden Ausfall der Steuerebene; bestehende
Verbindungen zwischen den Knoten laufen dabei weiter.
Realistischer Aufwand: Nach dem Aufsetzen sind es ein paar Minuten pro Monat – Knotenliste
durchsehen, alte Geräte mit headscale nodes delete entfernen, abgelaufene Schlüssel aufräumen.
Dazu ein bewusster Termin pro Quartal für das Headscale-Update, weil das eben nicht unbeaufsichtigt
laufen sollte.
Aufräumen gehört dazu. Geräte, die du nur einmal brauchst, legst du mit
preauthkeys create --ephemeral an – solche Knoten verschwinden nach 30 Minuten Inaktivität von
selbst (einstellbar über node.ephemeral.inactivity_timeout). Alles andere bleibt in der Liste stehen, bis du es löschst, und jeder tote Eintrag ist ein
Schlüssel, der theoretisch noch gültig ist.
Was Headscale nicht kann
Feedback per E-Mail: feedback@serverkueche.de
Das könnte dir auch schmecken


