Teil 4: Eigene Web-Anwendungen freigeben
Angenommen, du hast irgendwo in deinem Zuhause (auf einem NAS, Raspberry Pi, alten PC, o. ä.) bereits Tailscale installiert und mit deinem Headscale-Server verbunden (siehe Teil 3). Jetzt willst du eine dort laufende Web-Anwendung erreichbar machen, entweder nur für Geräte in deinem Tailnet, oder für die ganze Welt.
Nimm als Beispiel an, das Gerät hat die Tailscale-IP 100.64.0.10, und eine Anwendung läuft dort auf Port 9000.
Fall 1: Schöne URL, nur im Tailnet, ganz ohne Portnummer
Headscale kann eigene DNS-Einträge für dein Tailnet vergeben ("Extra DNS Records"). Der Trick, um die Portnummer wegzubekommen: Der Eintrag zeigt nicht direkt auf die App-IP, sondern auf die Tailscale-IP deines Headscale-Servers selbst, und Caddy übernimmt dort die Portweiterleitung.
Ergänze in ~/headscale/headscale/config/config.yaml, innerhalb des dns:-Blocks:
dns:
# ... bestehende Einträge ...
extra_records:
- name: "meineapp.internal.example.com"
type: "A"
value: "100.64.0.1" # Tailscale-IP DEINES Headscale-Servers, nicht der App
⚠️ Der Block muss wirklich innerhalb von
dns:stehen. Außerhalb wird er von Headscale stillschweigend ignoriert, auch wenn die Datei syntaktisch gültig bleibt.
cd ~/headscale
docker compose up -d --force-recreate headscale
In der Caddyfile (/etc/caddy/Caddyfile), mit explizitem http://, damit Caddy kein Zertifikat versucht:
# /etc/caddy/Caddyfile
http://meineapp.internal.example.com {
reverse_proxy 100.64.0.10:9000
}
sudo systemctl reload caddy
Test von einem Tailnet-Gerät:
curl -I http://meineapp.internal.example.com
Fall 2: Öffentlich erreichbar, auch ohne VPN
⚠️ Verwende dafür niemals deine MagicDNS-Basisdomain (
internal.example.comin dieser Anleitung). Nutze eine andere Subdomain oder deine Hauptdomain direkt.
-
DNS-Eintrag anlegen: A-Record, z. B.
meineapp.example.com, zeigt auf die öffentliche IP deines Headscale-Servers. -
Caddy-Block, dieses Mal ohne
http://-Präfix, damit Caddy automatisch ein Let's-Encrypt-Zertifikat holt:
# /etc/caddy/Caddyfile
meineapp.example.com {
reverse_proxy 100.64.0.10:9000
}
sudo systemctl reload caddy
- Testen:
curl -I https://meineapp.example.com
Möglicher Stolperstein: Manche Apps prüfen den Host-Header (CSRF-Schutz) und lehnen Anfragen unter einer unbekannten Domain ab. Falls Login/Formulare nach dem Umstieg fehlschlagen, meist hilft eine Umgebungsvariable wie CSRF_TRUSTED_ORIGINS in der jeweiligen App-Konfiguration.
Entscheidungshilfe
| Situation | Lösung |
|---|---|
| Familie soll sich einen Namen merken, kein Zugriff von außerhalb des Tailnets nötig | Fall 1 |
| Zugriff auch ohne VPN/unterwegs nötig | Fall 2 |
Das war's mit dem Kern der Anleitung! Falls du auch einen Unraid-Server einbinden willst, gibt's dafür noch einen Bonus-Teil.