Self-hosted URL-Shortener, erreichbar unter short.nettailor.net.
- Quelle: github.com/thedevs-network/kutt
- Live-Instanz: short.nettailor.net
- Stack: Komodo, Git-Repo-Modus, Quelle: eigenes Gitea-Repo
kutt-stack
Setup
Drei Services (kutt, postgres, redis) auf dem Hetzner-VPS, via Komodo aus einem eigenen Compose-Repo deployed.
- Secrets (
JWT_SECRET,DB_PASSWORD) direkt als Komodo-Stack-Environment-Variablen gesetzt (nicht als_FILE-Secrets im Repo) – einfacher, da Komodo sie intern verschlüsselt und man sich das Verteilen von Secret-Dateien auf den Host spart. DISALLOW_REGISTRATION: "true"dauerhaft gesetzt. Für die Admin-Ersteinrichtung einmalig auf"false"umgestellt, registriert, danach zurückgesetzt.- Container
kuttläuft ohne Authentik Forward Auth davor – anders als sonst üblich in diesem Setup.
⚠️ Wichtig: Kein Forward Auth vor URL-Shortenern
Anders als bei Stirling PDF, Grafana & Co. darf hier nicht die komplette Domain hinter Authentik Forward Auth liegen. Kurzlinks müssen für jeden anonymen Klick öffentlich erreichbar sein – sonst landet jeder externe Besucher, der auf einen short.nettailor.net/xyz-Link klickt, erst auf der Authentik-Login-Seite statt beim Ziel. Kutt bringt sein eigenes Login-System für Dashboard/API/Admin mit, das reicht als Zugriffsschutz für die Verwaltung.
Netzwerk (NPM-Erreichbarkeit)
Bestätigt die generelle Komodo-Lektion: NPM-proxied Container müssen explizit ins proxy-Netzwerk. Ursprüngliche Compose-Datei hatte kutt nur mit Host-Port-Mapping (127.0.0.1:3000:3000) – das reicht nicht, wenn NPM selbst containerisiert im proxy-Netz läuft und nicht auf dem Docker-Host-Netzwerk-Namespace sitzt.
Fix: ports: beim kutt-Service entfernt, stattdessen zweites Netzwerk proxy: external: true ergänzt und den Service dort zusätzlich zum internen default-Netz reingehängt. NPM zeigt dann per Container-Name (kutt) statt IP auf den Service.
🔧 Lessons Learned: AdGuard-Cache nach neuem DNS-Record
Datum: August 2026
Nach dem Anlegen des A-Records für short.nettailor.net lieferte dig short.nettailor.net +short lokal weiterhin leer, obwohl dig @1.1.1.1 short.nettailor.net +short bereits die korrekte IP zurückgab. Auch curl schlug mit Could not resolve host fehl.
Ursache: Doppelter Cache-Effekt:
- AdGuard Home hatte vermutlich einen negativen Cache-Eintrag von vor dem Anlegen des DNS-Records – Query-Log zeigte zwar “Verarbeitet”, aber mit auffällig kurzen Antwortzeiten (~0,2 ms), untypisch für eine echte Upstream-Abfrage.
- macOS’
mDNSRespondercached zusätzlich eigenständig, unabhängig vondig-Ergebnissen –digundcurlnutzen nicht zwingend denselben Auflösungspfad.
Fix:
# macOS lokal:
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponderBei AdGuard selbst hilft Einstellungen → DNS-Einstellungen → Cache leeren, notfalls Container-Neustart.
Merke: Bei “DNS liefert nichts, obwohl der Record längst existiert” immer beide Cache-Ebenen prüfen (lokaler Resolver und macOS-eigener DNS-Cache), nicht nur den Router/AdGuard.
Custom Domains
Kutt unterstützt zusätzliche Domains neben der DEFAULT_DOMAIN (Settings → Custom Domain). Die im Kutt-Settings-UI vorgeschlagene Beispiel-IP ist die von kutt.it – bei Self-Hosting muss stattdessen auf die eigene VPS-IP gezeigt werden. Für eine zusätzliche Domain: A-Record auf die VPS-IP, eigener NPM-Proxy-Host (gleicher Forward-Target kutt:3000, eigenes Let’s-Encrypt-Zertifikat), danach Domain in Kutt unter Settings eintragen.
Aktive Domains:
| Domain | Zweck |
|---|---|
short.nettailor.net | Default-Domain |
ghstbx.de | Custom Domain |
veedel.net | Custom Domain |
Jede zusätzliche Domain braucht einen eigenen NPM-Proxy-Host + eigenes Let’s-Encrypt-Zertifikat, auch wenn sie letztlich denselben Kutt-Container (kutt:3000) anspricht.
Status
- Compose-Stack (kutt, postgres, redis) über Komodo deployed
-
proxy-Netzwerk korrekt eingebunden, NPM-Proxy-Host mit Let’s Encrypt - DNS-Record gesetzt, Cache-Probleme gelöst
- Admin-Account angelegt, Registration wieder gesperrt
- Custom Domains
ghstbx.deundveedel.netergänzt
Erstellt: 2026-08-14 · Autor: Philipp