Skip to main content

RFC 2136 (Dynamic DNS)

Use RFC 2136 dynamic update to let CertAutoPilot add and remove the _acme-challenge TXT record on a DNS server you host yourself — BIND, PowerDNS, Knot, or a Windows DNS Server — instead of a cloud DNS API.

This is the answer to "my authoritative DNS is my own server; how do you write the challenge record?" You enable dynamic updates on the zone and point CertAutoPilot at the server.

How it works

For every DNS-01 challenge the worker sends a standard DNS UPDATE message (RFC 2136) to your DNS server: Present adds TXT _acme-challenge.<name>, the CA validates it, then CleanUp deletes it. Fully automatic on every renewal — no manual DNS edits.

Choose an authentication mode

Pick the Auth mode in the credential form; fill only that mode's fields.

ModeFieldsUse whenSecurity
TSIG (shared key)nameserver + tsig_key + tsig_secret (+ algorithm)BIND / PowerDNS / Knot and other RFC 2845 serversGood — HMAC-signed
GSS-TSIGnameserver + the tsig_gss_* fieldsWindows AD-integrated zone ("Secure only")Best on Windows — Kerberos, ties to an AD account
Nonsecurenameserver onlyA zone explicitly set to accept unsigned updatesWeak — firewall + a dedicated zone
Windows DNS does not do plain TSIG

Windows DNS Server does not implement RFC 2845 shared-key TSIG for dynamic updates. On Windows use GSS-TSIG (for "Secure only" zones) or Nonsecure. Plain TSIG is for BIND/PowerDNS/etc. If you'd rather not set up Kerberos on the CertAutoPilot host, use the Windows DNS (WinRM) provider instead — it writes the record over WinRM/PowerShell with no TSIG or Kerberos.

What is TSIG / GSS-TSIG?

TSIG (RFC 2845) authenticates a DNS UPDATE by signing it with a shared secret key (an HMAC); the server only accepts updates carrying a valid signature. This is what BIND and most non-Windows servers use.

GSS-TSIG (RFC 3645) is the same idea but the key is negotiated via Kerberos instead of a pre-shared secret — this is what Windows calls "secure dynamic update": the client authenticates as an Active Directory account and the DNS server checks its permission. No static secret to distribute.

Nonsecure means no signature — the server accepts any well-formed UPDATE. Only safe on an isolated/firewalled network.

TSIG setup (BIND / PowerDNS / …)

Generate a key and grant it update rights on the zone:

tsig-keygen -a hmac-sha256 acme-update. > acme.key
# named.conf
key "acme-update." { algorithm hmac-sha256; secret "BASE64SECRET=="; };
zone "example.com" {
type primary;
file "example.com.zone";
update-policy { grant acme-update. name _acme-challenge.example.com. TXT; };
};

In the credential form choose Auth mode = TSIG and enter tsig_key = acme-update., tsig_secret = BASE64SECRET==, and the matching Algorithm (the one you passed to tsig-keygen -a, e.g. HMAC-SHA256). The algorithm must match the key — pick it from the dropdown.

GSS-TSIG setup (Windows secure dynamic update)

For a Windows AD-integrated "Secure only" zone. Uses an AD account's username + password — the CertAutoPilot host does not need to be domain-joined.

  1. In DNS Manager keep the zone at Secure only. Grant an AD service account (e.g. svc-acme) Write on the zone (zone → Security tab), or delegate a _acme-challenge.<domain> sub-zone and grant it only there.

  2. In the credential form choose Auth mode = GSS-TSIG and enter the Realm (AD domain, UPPERCASE), Username, Password.

  3. On the Linux host running CertAutoPilot, provide a minimal /etc/krb5.conf (Kerberos is pure-Go here — no libgssapi/cgo needed):

    [libdefaults]
    default_realm = CORP.EXAMPLE.COM
    dns_lookup_kdc = true
    [realms]
    CORP.EXAMPLE.COM = { kdc = dc1.corp.example.com }

    Requirements: the host can reach a KDC (domain controller) on port 88, clock skew < 5 min with the DC, and the account can update the zone. No domain-join.

    KRB5_CONFIG overrides the location — and when it is set but points at a file that cannot be read, that is an error rather than a fall back to /etc/krb5.conf.

  4. Press Test on the credential. With no test domain given it checks the Kerberos configuration this mode depends on: that the file exists and parses, and that the realm you entered either has a [realms] entry or can be discovered through dns_lookup_kdc = true. It contacts no KDC and writes no record. A missing or realm-less krb5.conf used to pass this test and fail at the first issuance instead.

Prefer WinRM if Kerberos is inconvenient

If setting up krb5.conf / KDC access on the Linux host is undesirable, the Windows DNS (WinRM) provider achieves the same result over your existing WinRM admin access — and its own Kerberos option needs no host setup at all.

This is the only Kerberos path in CertAutoPilot that reads a file. Every other one — WinRM, IIS, Exchange and the Windows DNS provider — builds its Kerberos configuration in memory and finds the KDC through a DNS SRV lookup, so it needs nothing on the host. GSS-TSIG is different because the negotiation happens inside the ACME library, which offers no way to hand it a configuration; it reads KRB5_CONFIG or /etc/krb5.conf itself.

Enable dynamic updates on a Windows zone

DNS Manager → zone → PropertiesGeneralDynamic updates:

  • Secure only — AD-integrated zones. Use GSS-TSIG.
  • Nonsecure and secure — allows unsigned updates. Use Nonsecure mode, and only with the hardening below.
  • None — disabled; RFC 2136 cannot work.

PowerShell: Set-DnsServerPrimaryZone -Name "example.com" -DynamicUpdate "Secure" (or "NonsecureAndSecure").

Add the credential

  1. Settings → DNS CredentialsNewRFC 2136 (Dynamic DNS).
  2. Nameserver — the DNS server as host:port, e.g. 10.0.0.5:53.
  3. Auth mode — Nonsecure / TSIG / GSS-TSIG, then fill that mode's fields.
  4. Test connectivitySave.

Config fields

FieldModePurpose
nameserverallDNS server accepting updates, as host:port.
auth_modeallnonsecure / tsig / gss. Required when updating a credential through the API — it tells CertAutoPilot to clear the other mode's fields. Omitting it leaves stale credentials in the stored config, so a TSIG → nonsecure switch would keep signing.
tsig_keyTSIGTSIG key name (e.g. acme-update.).
tsig_secretTSIGBase64 TSIG secret.
tsig_algorithmTSIGPick to match your key (default hmac-sha256.).
tsig_gss_realmGSS-TSIGKerberos realm, e.g. CORP.EXAMPLE.COM.
tsig_gss_usernameGSS-TSIGAD account allowed to update the zone.
tsig_gss_passwordGSS-TSIGThat account's password.

Secrets (tsig_secret, tsig_gss_password) are encrypted at rest and never returned by the API.

Security hardening

  • Prefer TSIG or GSS-TSIG over nonsecure. If you must use nonsecure, firewall port 53 to the worker IPs.
  • Delegate a challenge-only sub-zone and grant update rights only there — never on your production zone.
  • Least-privilege: the key / AD account should be able to write only TXT _acme-challenge.*.

Propagation

The record is written straight onto the authoritative server, so propagation is near-instant. If the zone is replicated across DCs/secondaries, point Settings → General → DNS Resolvers at the server you update. See Propagation settings.

Troubleshooting

  • "bad signature" / NOTAUTH — TSIG key name/secret/algorithm mismatch (must match the server's key exactly), or a plain-TSIG update sent to a Windows "Secure only" zone (use GSS-TSIG or WinRM).
  • "REFUSED" — dynamic updates not enabled on the zone, or the mode doesn't match ("Secure only" needs GSS-TSIG), or the key/account lacks write permission.
  • GSS-TSIG can't get a ticket — the host can't reach the KDC (port 88), krb5.conf realm wrong, or clock skew > 5 min. Press Test first: it rules out a missing, unparseable or realm-less krb5.conf without contacting anything, leaving only reachability and clock skew.
  • Timeout — firewall blocking UDP/TCP 53, or the wrong nameserver host:port.

See also