Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Hetzner DynDNS Bridge: Hetzner Console API und DNS Console API

profile picture
Author
woehrl
Published
2026-02-03
Time to read
8 minutes reading time

About the author- S/W Architect, Full-Stack Senior Developer

Einführung

Deine IPv4/IPv6 soll folgen wie ein treuer Hund, ohne dass du DNS von Hand pflegen musst? Dieses kleine PHP-Skript spielt DynDNS-Server, spricht sowohl die Hetzner Console API als auch die Legacy DNS Console API und versteht sich mit Routern wie einer Fritz!Box. Zuerst kommt die Schritt-für-Schritt-Anleitung für Einsteiger, danach die Nerd-Ecke mit den Details. Neue Zonen lassen sich seit 10. November 2025 nicht mehr in der DNS Console anlegen; plane die Migration in die Hetzner Console ein und halte DNS Console nur während des Umzugs aktiv.

Voraussetzungen

  • Ein Hetzner-Account mit mindestens einer DNS-Zone (Hetzner Console oder DNS Console während der Migration).
  • PHP mit den Erweiterungen curl und SQLite3 (Webspace oder kleine VM reicht).
  • Einen Ort für das PHP-Skript und einen Cronjob alle paar Minuten.
  • Einen Client, der eine DynDNS-URL aufrufen kann (Router, NAS oder ein einfacher curl-Aufruf).

Schritt 0 - Beispiel-Setup auf Debian/Ubuntu

Falls du von einem blanken Debian/Ubuntu startest, bringen dich diese Befehle zu einem testbaren Endpunkt:

  • Voraussetzungen installieren und Ordner für Skripte erstellen
    sudo apt update
    sudo apt install -y apache2 libapache2-mod-php php-cli php-curl php-sqlite3
    sudo a2enmod rewrite
    
    sudo mkdir -p /var/www/hetzner-ddns
    sudo chown -R www-data:www-data /var/www/hetzner-ddns

  • Apache-Seite erstellen

    Passe ServerName auf deinen DynDNS-Endpunkt an. In Produktion solltest du HTTPS (z. B. Let's Encrypt) nutzen.

    cat <<'EOF' | sudo tee /etc/apache2/sites-available/hetzner-ddns.conf
    <VirtualHost *:80>
        ServerName ddns.example.com
        DocumentRoot /var/www/hetzner-ddns
        <Directory /var/www/hetzner-ddns>
            AllowOverride All
            Require all granted
        </Directory>
    </VirtualHost>
    EOF

  • Seite aktivieren
    sudo a2ensite hetzner-ddns
    sudo apachectl configtest
    sudo systemctl reload apache2

Schritt 1 - Dateien besorgen

Nutze die zu diesem Tutorial gebündelten Dateien in tutorials/hetzner-ddns-bridge/scripts:

Gespiegelt von https://github.com/woehrl/hetzner-dyndns, Commit 11582e6. Kopiere sie auf deinen Webspace oder eine kleine VM.

Für das Beispiel-Setup aus "Schritt 0" müssen die Dateien in /var/www/hetzner-ddns gespeichert werden.

Du brauchst mindestens:

/var/www/hetzner-ddns
├─ hetzner_dyndns.php
├─ hetzner_dyndns.config.php.dist
├─ .htaccess                         Die Datei von GitHub
└─ hetzner_dyndns_listhosts.php      Optional

Beispiel-Befehle:

export path="https://raw.githubusercontent.com/hetzneronline/community-content/refs/heads/master/tutorials/hetzner-ddns-bridge/scripts"
cd /var/www/hetzner-ddns

# Führe folgenden Befehl im Terminal aus,
# um die Dateien zu bestimmen
files=(
  hetzner_dyndns.php
  hetzner_dyndns.config.php.dist
  .htaccess
  hetzner_dyndns_listhosts.php
)

# Führe folgenden Befehl im Terminal aus,
# um die zuvor bestimmten Dateien zu kopieren
for f in "${files[@]}"; do
  curl "$path/$f" | sudo tee "$f" >/dev/null
done

Schritt 2 - Config anlegen

sudo cp hetzner_dyndns.config.php.dist hetzner_dyndns.config.php

Bearbeite hetzner_dyndns.config.php:

Beschreibung
auth_user Optional: Username für HTTP Basic Auth. Wenn leer, wird update verwendet.
auth_password Bestimme ein starkes, geteiltes Passwort. Dein Router nutzt es.
api_order Lege fest, welche API zuerst probiert wird: Verwende ['console', 'dns'] für Migration oder ['console'], wenn alle Zonen auf der neuen API liegen.
console_token
dns_token
Tokens hinzufügen:
  • Hetzner Console: Erstelle ein API-Token in der Hetzner Console und trage es bei console_token ein.
  • DNS Console (legacy): Erstelle ein DNS-Token in der DNS Console und trage es bei dns_token ein (nur wenn du dort noch Zonen hast).
zone_name Wenn die IP-Adresse für eine Subdomain (z.B. sub.example.com) aktualisiert werden soll, muss hier die Hauptdomain (z.B. example.com) angegeben werden.
auth_realm Optional: Wähle ein Label (z. B. "dynbridge").
history_db Optional: Zeige auf einen beschreibbaren Pfad (z. B.
DIR . '/hetzner_dyndns.sqlite3').
TTL Optional: Passe die TTL pro Realm an, wenn es schneller oder langsamer propagieren soll.

Schritt 3 - Sicher ins Netz stellen

  • Halte hetzner_dyndns.config.php aus öffentlichen Repos und Verzeichnislisten heraus.
  • Stelle sicher, dass .htaccess die DynDNS-Endpunkte auf das Skript umschreibt, damit alte Clients funktionieren:
    RewriteEngine On
    RewriteRule ^(nic/update|v3/update)$ hetzner_dyndns.php [L,QSA]
  • Falls nötig, sorge dafür, dass der PHP-User in die SQLite-Datei und das Debug-Log schreiben darf.

Schritt 4 - Update testen

  • Baue die Test-URL (ersetze Domain und Host):
    https://dein-ddns-host.example.com/nic/update?hostname=myhost.example.com&myip=203.0.113.10
  • Nutze HTTP Basic Auth mit auth_user/auth_password (User defaultet auf update, wenn leer). DynDNS-Clients senden meist irgendeinen Usernamen plus das Passwort; per curl geht es so:
    curl -u user:deinPasswort \
      "https://dein-ddns-host.example.com/nic/update?hostname=myhost.example.com&myip=$(curl -s ifconfig.me)"
  • Erfolgreiche Antworten sind good <ip> (aktualisiert) oder nochg <ip> (nichts zu tun). Alles andere: ins Debug-Log schauen.

Schritt 5 - Automatisieren

  • Cron alle 5 Minuten (nach Bedarf anpassen):
    */5 * * * * php /path/to/hetzner_dyndns.php --cron --realm=default
  • Richte deinen Router oder dein NAS auf dieselbe nic/update-URL mit dem gesetzten Passwort ein. IPv6 klappt, wenn der Client myipv6 mitsendet.
  • Legacy-Clients dürfen weiterhin X-Authentication: <passwort> oder ?p=<passwort> (nur Passwort) senden, empfohlen ist Basic Auth.

Schritt 6 - Kurzer Troubleshooting-Spickzettel

  • 401 oder Auth-Prompt: Passwort stimmt nicht oder .htaccess greift nicht.
  • not_found: falsche Zone oder Hostname, oder fehlende Token-Rechte.
  • SQLite-Schreibfehler: Dateirechte anpassen oder DB in einen beschreibbaren Pfad verschieben.
  • Nichts ändert sich: api_order prüfen und das richtige Token pro Realm setzen.

Nerd-Ecke (so funktioniert es wirklich)

  • Architektur im Überblick
    • Ein PHP-Skript, eine Config, eine SQLite-DB. DynDNS-Aufrufe (/nic/update oder /v3/update) werden via .htaccess auf hetzner_dyndns.php umgeschrieben.
    • Das Skript authentifiziert mit Benutzername/Passwort, parst Hostname und optionales realm, cached bekannte Records in SQLite und antwortet sofort mit good, wenn sich nichts geändert hat.

  • Konfig-Details
    • Gemeinsame Einstellungen: auth_user, auth_password, auth_realm, history_db sowie optional debug/debug_log.
    • Benachrichtigungen: notifications.enabled aktivieren, php oder smtp wählen, Empfänger setzen und entscheiden, ob bei Erfolg, Fehler oder beidem gemailt wird.
    • Realms: pro Realm ttl, api_order, zone_name, console_token und dns_token. Setze zone_name, wenn der DynDNS-Endpunkt auf einer Subdomain liegt, du aber die Hauptzone aktualisierst.

  • "Hetzner Console"-API-Ablauf (aktuell)
    1. Zone über /zones?name=<zone> mit dem Hetzner Console API-Token finden.
    2. RRsets über /zones/{id}/rrsets (A und AAAA) holen.
    3. RRset-Namen mit dem Host abgleichen (inkl. @ am Apex).
    4. set_records aufrufen, um die IPs zu ersetzen. Erfolgreich = Action-Response; Fehler melden not_found oder fehlende Rechte.

  • "DNS Console"-API-Ablauf (Legacy)
    1. Zonen-ID mit /zones?name=<zone> über dns_token holen.
    2. A/AAAA-Record-IDs finden, in SQLite cachen und per PUT /records/{id} aktualisieren.
    3. Fehler bleiben als needs_sync für Cron-Retries markiert.

  • Wechsel zwischen den APIs
    • Nutze ['console', 'dns'] während der Migration. Wenn Hetzner Console not_found sagt, fällt das Skript auf DNS Console zurück.
    • Wenn eine Zone komplett auf Hetzner Console läuft, dns_token entfernen oder auf ['console'] umstellen, um Legacy-Calls zu sparen und dem DNS-Console-Abschaltplan voraus zu sein.
    • Nach Config-Änderungen php hetzner_dyndns.php --cron ausführen, um offene Jobs abzuarbeiten und beide APIs zu testen.

  • Mehrere Zonen und Realms
    • Lege pro Zone oder Subdomain einen Realm an. Beispiel: Realm gjsi.de und ddns.gjsi.de mit unterschiedlichen Tokens und TTLs.
    • Nutze realm=<name> im DynDNS-Query-String, wenn du mehrere Domains über denselben Endpunkt bedienst.
    • Der optionale CLI-Helfer hetzner_dyndns_listhosts.php kann gecachte IPv4/IPv6 pro Realm ausgeben, ohne den HTTP-Endpunkt zu treffen.

  • Benachrichtigungen und Observability
    • E-Mails zu Erfolgen und Fehlern über PHP mail() oder SMTP.
    • debug und debug_log zeichnen Requests und Responses beider APIs plus Benachrichtigungsstatus auf.
    • Cron-Summen listen Gesamtzahl, Erfolge, Fehler und welche API jeden Host bearbeitet hat.

  • Sicherheit und Deployment
    • .htaccess blockiert direkte Zugriffe auf PHP und SQLite und lässt nur die DynDNS-Endpunkte durch.
    • Tokens nur auf DNS scopen und regelmäßig rotieren.
    • SQLite-DB und Debug-Log müssen für den PHP-User schreibbar sein; nach Möglichkeit außerhalb öffentlicher Webroots ablegen.
    • DynDNS-Endpunkt per HTTPS bereitstellen. Reines HTTP würde dein Passwort verraten.

Ergebnis

Die Bridge liefert dir einen freundlichen DynDNS-Endpunkt, der Hetzners API-Umstellung überlebt. Starte mit dem Schnellstart, damit Updates laufen, und wirf dann einen Blick in die Nerd-Ecke, wenn du Realms, Benachrichtigungen oder das Verhältnis zwischen Hetzner Console und DNS Console feintunen willst.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get €20/$20 free credit!

Valid until: 31 December 2026 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more