- subdomains-Tabelle (n DNS-Namen je Benutzer) inkl. Migration vom alten Einzel-Subdomain-Schema in database.init_db() - Benutzeranlage/Verwaltung: mehrere Subdomains hinzufuegen/entfernen - /nic/update aktualisiert alle Subdomains des Benutzers bzw. die per ?hostname= gewaehlte(n); eine Antwortzeile je Subdomain - Dashboard/Users-Templates auf das neue Modell umgestellt - README.md mit Setup, Plesk-Konfig, Router-Einrichtung und Endpoint-Doku - .gitignore: __pycache__/ und *.pyc Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.0 KiB
DynDNS Manager für Plesk
Ein kleiner, selbst gehosteter DynDNS-Server mit Web-Oberfläche. Er nimmt DynDNS-v2-Updates (wie sie z. B. ein Telekom Speedport unter „Anderer Anbieter" sendet) entgegen und trägt die gemeldete IP-Adresse über die Plesk REST-API als A-Record in deine DNS-Zone ein.
- Mehrere DynDNS-Benutzer, mehrere Subdomains (DNS-Namen) pro Benutzer
- Admin-Weboberfläche (Flask + Bootstrap) zum Verwalten von Benutzern, Subdomains und Plesk-Einstellungen
- Update-Log pro Subdomain
- Läuft als Docker-Container hinter einem nginx-TLS-Proxy
Schnellstart
# 1. Container bauen und starten
docker compose up -d --build
# 2. Weboberfläche öffnen (lokal, hinter nginx -> https)
# http://127.0.0.1:5080
# Standard-Login: admin / admin (sofort ändern!)
Die SQLite-Datenbank wird beim ersten Start automatisch unter ./data/dyndns.db
angelegt (Volume-Mount in docker-compose.yml). Existiert die Datei nicht, wird
sie samt Tabellen erzeugt; ein Default-Admin (admin / admin) wird angelegt.
Konfiguration
Umgebungsvariablen (docker-compose.yml)
| Variable | Bedeutung | Default |
|---|---|---|
DB_PATH |
Pfad zur SQLite-Datei im Container | /data/dyndns.db |
SECRET_KEY |
Flask-Session-Key — unbedingt ändern (openssl rand -hex 32) |
zufällig pro Start |
Wichtig: Das Volume mountet ein Verzeichnis (
./data:/data), nicht die Datei direkt. Würde man die noch nicht existierende Datei mounten (./dyndns.db:/data/dyndns.db), legt Docker sie als Verzeichnis an und SQLite scheitert mitunable to open database file.
Plesk-Einstellungen (in der Weboberfläche → Einstellungen)
| Feld | Beispiel | Bedeutung |
|---|---|---|
| Plesk-URL | https://plesk.example.com:8443 |
Basis-URL der Plesk-Installation |
| API-Key | XXXXXXXX-... |
Plesk REST-API-Key (in Plesk unter API-Schlüssel erzeugen) |
| Basis-Domain | example.com |
DNS-Zone, in die die A-Records geschrieben werden |
| SSL verifizieren | ☑/☐ | bei selbstsigniertem Plesk-Zertifikat abschalten |
Mit Verbindung testen lässt sich die API prüfen.
Benutzer & Subdomains anlegen
-
In der Weboberfläche auf Benutzer → Benutzer anlegen.
-
DynDNS-Benutzername und Passwort vergeben (das sind die Zugangsdaten, die später im Router eingetragen werden).
-
Eine oder mehrere Subdomains eintragen — getrennt durch Komma, Leerzeichen oder Zeilenumbruch, z. B.:
mypc nas routerZusammen mit der Basis-Domain (
example.com) ergeben sich daraus die Hostnamenmypc.example.com,nas.example.com,router.example.com.Auch mehrstufige Namen sind erlaubt (
pc.home→pc.home.example.com), solange die Records in der DNS-Zone der Basis-Domain liegen.
Weitere Subdomains lassen sich später jederzeit über das +-Symbol in der Benutzerzeile hinzufügen oder per × am Badge entfernen.
Hinweis: Der DNS-A-Record wird nicht schon beim Anlegen in Plesk erstellt, sondern erst beim ersten DynDNS-Update vom Client (lazy). Bis dahin zeigt das Dashboard „noch kein Update".
Router / Speedport einrichten
Im Router unter DynDNS „Anderer Anbieter" konfigurieren:
| Feld | Wert |
|---|---|
| Update-URL | https://dyndns.example.com/nic/update?hostname=<domain>&myip=<ipaddr> |
| Domainname | z. B. mypc.example.com |
| Benutzername | der angelegte DynDNS-Benutzername |
| Passwort | das zugehörige Passwort |
Die Platzhalter <domain> und <ipaddr> füllt der Router automatisch.
Authentifiziert wird per HTTP Basic Auth (Benutzername/Passwort).
Update-Endpoint /nic/update
Standard-DynDNS-v2-Protokoll:
GET /nic/update?hostname=mypc.example.com&myip=203.0.113.7
Authorization: Basic <user:pass>
Verhalten:
hostnameangegeben → nur die passende(n) Subdomain(s) dieses Benutzers werden aktualisiert. Erlaubt ist der volle FQDN (mypc.example.com) oder nur das Label (mypc); mehrere durch Komma getrennt.hostnameweggelassen → alle Subdomains des Benutzers werden auf die gemeldete IP gesetzt.myip(oderip) bestimmt die Adresse; fehlt sie, wird die Quell-IP des Requests verwendet.
Antworten (eine Zeile pro Subdomain):
| Antwort | Bedeutung |
|---|---|
good <ip> |
Record erfolgreich gesetzt |
nochg <ip> |
IP unverändert, nichts zu tun |
nohost |
Benutzer hat keine (passende) Subdomain |
badauth |
Benutzername/Passwort falsch |
911 |
Plesk nicht konfiguriert (URL/Key/Domain fehlt) |
dnserr |
Fehler beim Schreiben in Plesk (siehe Log) |
Beispiel-Test mit curl:
curl -u stefan:geheim \
"https://dyndns.example.com/nic/update?hostname=mypc.example.com&myip=203.0.113.7"
TLS / Reverse Proxy
Der Container lauscht nur lokal (127.0.0.1:5080). Die TLS-Terminierung
übernimmt nginx — eine Beispielkonfiguration liegt in
nginx-subdomai-example.conf. Domain in Plesk
anlegen, Let's-Encrypt-Zertifikat ausstellen, dann die Datei als zusätzliche
nginx-Direktiven einbinden.
Architektur
app/
├── main.py Flask-Routen: Login, Dashboard, Benutzer/Subdomains, /nic/update
├── database.py SQLite-Schema, Migration, Settings-Helfer
├── plesk.py Plesk-REST-API: Verbindungstest + A-Record anlegen/aktualisieren
├── wsgi.py gunicorn-Einstieg (ruft init_db beim Start)
└── templates/ Bootstrap-Oberfläche
Datenmodell
dyndns_users— Zugangsdaten (Benutzername/Passwort), aktiv-Flagsubdomains— beliebig viele DNS-Namen je Benutzer (dyndns_user_id→dyndns_users.id), inkl. aktueller IP und Zeitpunkt des letzten Updatesupdate_log— Verlauf pro Subdomainadmin_users,settings— Admin-Login und Plesk-Konfiguration
Beim Start migriert init_db() automatisch ältere Datenbanken, die noch eine
einzelne subdomain-Spalte in dyndns_users hatten, in die neue
subdomains-Tabelle.
Lokale Entwicklung (ohne Docker)
cd app
pip install -r requirements.txt
export DB_PATH=./dev.db
export SECRET_KEY=dev
python main.py # http://127.0.0.1:5000