7.1 KiB
Hetzner DynDNS
Weboberfläche für mehrere Hetzner-DNS-Zonen, eine Pi-hole-v6-Verbindung, Subdomains und Benutzer. Aktivierte A- und AAAA-Records werden regelmäßig auf die aktuelle öffentliche IP gesetzt; lokale DNS-Einträge lassen sich direkt über die Pi-hole-API verwalten.
Starten
Die Datei compose.yml in Portainer, Dockge oder einem anderen Docker-Webinterface als Stack einfügen und starten.
Alternativ im ausgecheckten Repository:
docker compose up -d
Danach aufrufen:
http://IP-DES-DOCKER-HOSTS:9090
Beim ersten Start werden Datenbank und Verschlüsselungsschlüssel automatisch in getrennten Docker-Volumes angelegt. Es werden keine .env-Datei und kein manuell erzeugtes Secret benötigt.
Das Compose
services:
dyndns:
image: &image git.j-mahler.de/admin/domain-control-webinterface-prod:v1.4.3
restart: unless-stopped
stop_grace_period: 20s
ports: ["9090:8080"]
volumes: ["dyndns-data:/data", "dyndns-secrets:/secrets", "dyndns-update-control:/run/domain-control-update"]
labels: {de.j-mahler.domain-control.role: app}
read_only: true
tmpfs: ["/tmp:rw,noexec,nosuid,nodev,size=16m,mode=1777"]
security_opt: [no-new-privileges:true]
cap_drop: [ALL]
update-agent:
image: *image
restart: unless-stopped
user: "0:10001"
command: [update-agent]
healthcheck: {disable: true}
network_mode: none
volumes: ["/var/run/docker.sock:/var/run/docker.sock", "dyndns-update-control:/run/domain-control-update"]
read_only: true
tmpfs: ["/tmp:rw,noexec,nosuid,nodev,size=4m,mode=1777"]
security_opt: [no-new-privileges:true]
cap_drop: [ALL]
pids_limit: 32
mem_limit: 64m
volumes: {dyndns-data: {}, dyndns-secrets: {}, dyndns-update-control: {}}
Soll ein anderer Port verwendet werden, muss nur die linke Zahl geändert werden.
Aktualisieren
Eine vollständige Schritt-für-Schritt-Anleitung für WebUI, Docker Compose,
Portainer/Dockge und Rollbacks steht in UPDATE.md.
Administratoren können im Menü Update nach stabilen Releases suchen und eine neue Version direkt installieren. Dabei dürfen auch mehrere Versionen bis hin zu einem kompatiblen Major-Release übersprungen werden. Vor dem Neustart prüft der Agent Versionsgrenze, Agent-Protokoll, Datenbankvertrag, Laufzeitkonfiguration und Healthcheck des Ziel-Images. Gitea-Benutzername und wahlweise Passwort oder Token werden einmalig in der Weboberfläche hinterlegt; das Geheimnis wird mit dem Master-Key verschlüsselt gespeichert und weder an Templates noch an den Browser zurückgegeben.
v1.4.0 ist die sichere Basis für diesen Update-Weg. Eine ältere Installation wird einmalig mit Docker Compose auf v1.4.0 gebracht; danach kann der Agent auch spätere kompatible Releases direkt installieren. Web-App und Agent dürfen dabei unterschiedliche Versionsnummern haben: Maßgeblich ist das ausdrücklich ausgewiesene Protokoll. Verlangt ein Ziel-Image einen neueren Vertrag, bleibt der laufende Container unverändert und die Oberfläche fordert ein Compose-Update an.
Nur der separate, netzwerklose update-agent erhält Zugriff auf den Docker-Socket. Er kann ausschließlich das fest konfigurierte Anwendungs-Image ersetzen: Das neue Image wird vollständig geladen, bevor der laufende Container beendet wird, und erst nach erfolgreichem Healthcheck übernommen. Bei einem Fehler wird die vorherige Instanz automatisch wiederhergestellt. Ist Gitea oder die Registry nicht erreichbar, läuft der DNS-Updater unabhängig weiter und die zuletzt bekannte Update-Benachrichtigung bleibt erhalten.
Auf derselben Seite kann ein Administrator den vollständigen Anwendungscontainer geordnet neu starten. Dabei bleiben Daten-, Secret- und Steuer-Volumes unverändert. Der Neustart beendet den Prozess im Container; die in der unterstützten Compose-Konfiguration gesetzte Richtlinie restart: unless-stopped startet ihn anschließend automatisch wieder. Die Oberfläche erkennt die neue Prozessinstanz und verbindet sich selbstständig neu.
Alternativ lässt sich die Version weiterhin vollständig über Docker Compose aktualisieren. Dafür nur den konkret gepinnten Tag in der mit &image markierten Image-Zeile ändern; Web-App und Update-Agent verwenden dadurch garantiert dieselbe Version. Anschließend:
docker compose pull
docker compose up -d --force-recreate
Compose ersetzt beide Container und bindet die vorhandenen benannten Volumes wieder ein. docker compose down -v darf nicht verwendet werden, weil -v die Daten- und Secret-Volumes löschen würde. Der Ein-Klick-Updater verändert weder compose.yml noch Volumes. Vor einem späteren manuellen docker compose up muss der dort gepinnte Tag deshalb auf die gewünschte Version gesetzt werden. Meldet die WebUI Compose aktualisieren, unterstützt der vorhandene Agent den benötigten Vertrag nicht und beide Container werden auf diesem Weg gemeinsam aktualisiert.
Benutzer, Domains und Einstellungen bleiben in dyndns-data. Der Schlüssel für gespeicherte API-Tokens liegt in dyndns-secrets. Für ein vollständiges Backup müssen beide Volumes gesichert werden.
Funktionen
- mehrere Domains und getrennt verschlüsselte Hetzner-API-Tokens
- automatischer Import vorhandener A-/AAAA-Records
- DynDNS pro Subdomain und IP-Familie aktivierbar
- lokales Archiv statt Löschen von Hetzner-Records
- frei einstellbares Update-Intervall mit Countdown
- Admin- und Mitgliedskonten mit Domain- oder Subdomain-Rechten
- ausschließlich Administratoren verwalten Konten und Freigaben; Admin-Vollzugriff besitzt keine bearbeitbaren Einzelrechte
- automatische Release-Prüfung, Update-Benachrichtigung und kontrolliertes Ein-Klick-Update mit Rollback
- administrativer Container-Neustart mit automatischem Wiederverbinden der Weboberfläche
- eine Pi-hole-v6-Verbindung mit verschlüsseltem Anwendungspasswort und geschützter Anzeige nach erneuter Admin-Passwortprüfung
- lokale Pi-hole-DNS-Einträge für IPv4 und IPv6 anlegen, aktivieren/deaktivieren, bearbeiten, aus der WebUI trennen, wiederherstellen und vollständig löschen
Der Container muss die verbundene Pi-hole-Adresse direkt im internen Netz erreichen können. Pi-hole-Sitzungen werden nur für die jeweilige Aktion erstellt und danach aktiv beendet; dauerhaft gespeichert wird ausschließlich das mit dem Master-Key verschlüsselte Anwendungspasswort. Secret- und Datenverzeichnis werden auf 0700, Master-Key und SQLite-Datei auf 0600 gehärtet. Das Compose-Setup verwendet außerdem ein schreibgeschütztes Root-Dateisystem und ein begrenztes /tmp-Tmpfs. HTTPS mit gültigem Zertifikat ist empfohlen.
Damit ein Pi-hole-Anwendungspasswort lokale DNS-Einträge ändern darf, muss am Pi-hole webserver.api.app_sudo=true gesetzt sein; Pi-hole verwendet hierfür standardmäßig false. Zusätzlich darf der globale Schalter misc.readOnly nicht aktiviert sein. Bei einem Pi-hole-Docker-Container entspricht das beispielsweise FTLCONF_webserver_api_app_sudo: "true" und FTLCONF_misc_readOnly: "false".
Port 9090 verwendet zunächst unverschlüsseltes HTTP. Den Port daher nur in einem vertrauenswürdigen Netz freigeben und nicht offen ins Internet stellen.