Skip to content

ddclient: add Hetzner DNS provider#5082

Merged
AdSchellevis merged 1 commit intoopnsense:masterfrom
ArcanConsulting:add-hetzner-dns-provider
Dec 17, 2025
Merged

ddclient: add Hetzner DNS provider#5082
AdSchellevis merged 1 commit intoopnsense:masterfrom
ArcanConsulting:add-hetzner-dns-provider

Conversation

@ArcanConsulting
Copy link
Contributor

Add Hetzner DNS providers for ddclient

Summary

Adds native support for Hetzner DNS with both APIs:

  • Hetzner DNS - New Cloud API (api.hetzner.cloud) for migrated zones
  • Hetzner DNS Legacy - Old API (dns.hetzner.com) for zones not yet migrated

Hetzner is migrating their DNS service from DNS Console to Cloud Console. The old API will be shut down in May 2026.

Features

  • Bearer token authentication (Cloud API) / Auth-API-Token (Legacy API)
  • Supports A and AAAA records (auto-detected)
  • Supports multiple hostnames (comma-separated)
  • Supports both zone field and username field for zone name (backwards compatibility)
  • Handles FQDN and relative record names
  • Configurable TTL

Important: Backend Setting

Users must set the DynDNS backend to native for these providers to work:

  1. Go to Services → Dynamic DNS → Settings
  2. Set Backend to native
  3. Save and apply

The native backend dynamically loads Python-based providers, while the ddclient backend only supports services defined in ddclient itself.

Configuration

Hetzner DNS (new Cloud API)

Field Value
Service Hetzner DNS
Zone Your domain (e.g., example.com)
Password Hetzner Cloud API token
Hostname(s) Record(s) to update (e.g., dyn.example.com)

Get your token at Hetzner Cloud Console → Project → Security → API Tokens (Read & Write).

Hetzner DNS Legacy (old API - deprecated)

Field Value
Service Hetzner DNS Legacy (deprecated)
Zone Your domain (e.g., example.com)
Password Hetzner DNS Console API token
Hostname(s) Record(s) to update (e.g., dyn.example.com)

Get your token at dns.hetzner.com.

Migration Path

Users with zones still on the old DNS Console should:

  1. Use Hetzner DNS Legacy until they migrate
  2. Migrate their zone to Cloud Console
  3. Create a new Cloud API token
  4. Switch to Hetzner DNS

Testing

Tested with:

  • Single and multiple hostname updates
  • IPv4 (A records)
  • Zone lookup by name
  • Record creation and updates
  • Both Cloud and Legacy APIs

References

  Add native support for Hetzner Cloud DNS API (api.hetzner.cloud).
  Hetzner is migrating from dns.hetzner.com to Cloud Console,
  with the old API shutting down in May 2026.

  Features:
  - Bearer token authentication
  - A and AAAA record support
  - Multiple hostnames (comma-separated)
  - Configurable TTL
@dporki
Copy link

dporki commented Jan 31, 2026

Is it intended to not update the pre-existing record after reboot? I've noticed that it creates a new record just fine but after a reboot the record is not updated. Here are my steps to reproduce:

  1. Setup the provider (with token read+write access, no Record protection enabled)
  2. Enable it and see it first time creating the A record
  3. Reboot Opensense to get a new DHCP lease on WAN
  4. Record is not updated contrary to what the log states

Logs:
Initial successful creation:

2026-01-31T15:10:28 Notice ddclient Flush dyndns status to disk
2026-01-31T15:10:28 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] updated
2026-01-31T15:10:28 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] set new IP 80.132.66.180 for dummyhostname
2026-01-31T15:10:28 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] created dummyhostname A with 80.132.66.180
2026-01-31T15:10:28 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] updating dummyhostname (record: dummyhostname, type: A) to 80.132.66.180
2026-01-31T15:10:27 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] found zone ID 25717 for dummydomain.tld
2026-01-31T15:10:27 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] executing
2026-01-31T15:10:27 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] uses Hetzner for service
2026-01-31T15:09:28 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] not modified
2026-01-31T15:09:28 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] executing
2026-01-31T15:09:28 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] uses Hetzner for service

After reboot:

2026-01-31T15:14:19 Notice ddclient Flush dyndns status to disk
2026-01-31T15:14:19 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] updated
2026-01-31T15:14:19 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] set new IP 80.132.79.213 for dummyhostname
2026-01-31T15:14:19 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] updated dummyhostname A to 80.132.79.213
2026-01-31T15:14:19 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] updating dummyhostname (record: dummyhostname, type: A) to 80.132.79.213
2026-01-31T15:14:19 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] found zone ID 25717 for dummydomain.tld
2026-01-31T15:14:19 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] executing
2026-01-31T15:14:19 Notice ddclient Account REMOVED [hetzner - Home DynDNS IP] uses Hetzner for service

I have also checked the Hetzner account logs that shows a single successful " zone.rrset.update " activity after reboot but the RRSET is not updated at all and suck with the old IP. The log sadly does only state where the requests came from and not what has been tried to set.

@realizelol
Copy link
Contributor

Hey,

checkout his new script in his PR:
https://github.com/opnsense/plugins/pull/5091/files#diff-c4b83fc05c35eeb4b4492a69989304050f8c1b5f629b7a4da9d43ea9780ad6f0

There's already a workaround. Hetzner replies with code 200 to the PUT method but doesn't change anything.
So in the newer script the entry will be deleted and readded with the new ip instead of really updating/changing.

The new script is working fine for me. Maybe the script could be updated for ddclient - outside of his hetzner plugin, which maybe need some more time.

I personally subcripted #5091.

@dporki
Copy link

dporki commented Feb 1, 2026

@realizelol I did not see that it was already known. I've scripted it myself now with Monit and a custom script. I'll be watching for a fix to the native plugin or the ddclient. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants