Quick How-To deploy Certbot’s DNS-01 challenge for easy TLS certificate creation and renewal. Using Let’s Encrypt certificates with DNS-01 challenges makes certificate handling so much more fun.

Time-saver included, find the bottom. TL;DR: Case matters for once (for certbot).

The following is part of an Ansible recipe, the {{ FOO_BAR }} literals are Jinja2 variables. Substitute for your local requirements.

Create a key:

tsig-keygen -a HMAC-SHA512 {{ RFC2136_KEY_NAME }}

If using BIND, add this key to named.conf.local:

key "{{ RFC2136_KEY_NAME }}" {
  algorithm hmac-sha512;
  secret "{{ RFC2136_HMAC_SHA512_HASH }}";
};

and add these lines to your domain’s zone configuration:

update-policy {
  grant {{ RFC2136_KEY_NAME }} name _acme-challenge.{{ DDNS_DOMAIN }}. txt;
  grant {{ RFC2136_KEY_NAME }} name _acme-challenge.www.{{ DDNS_DOMAIN }}. txt;
  grant {{ RFC2136_KEY_NAME }} name _acme-challenge.smtp.{{ DDNS_DOMAIN }}. txt;
};

Lastly, create a DNS-01 challenge configuration file for certbot, /etc/letsencrypt/dns-01.ini:

dns_rfc2136_server = 127.0.0.1
dns_rfc2136_port = 53
dns_rfc2136_name = {{ RFC2136_KEY_NAME }}
dns_rfc2136_secret = {{ RFC2136_HMAC_SHA512_HASH }}
; Beware, case sensitive algo name!
dns_rfc2136_algorithm = HMAC-SHA512

You might need to yet install the DNS-01 challenge module for certbot:

apt install python3-certbot-dns-rfc2136

Reload/restart BIND, then check if this works:

certbot certonly --dry-run -v --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/dns-01.ini -d {{ DDNS_DOMAIN }}

You’re seeing the following error in your bind logs?

security: error: request has invalid signature: TSIG {{ RFC2136_KEY_NAME }}: tsig verify failure (BADKEY)

Check your certbot rfc2136 config file!

Make sure the certbot dns-01 challenge config file (/etc/letsencrypt/dns-01.ini) has the dns_rfc2136_algorithm correct: All upper-keys.

I.e.:”HMAC-SHA512″ instead of “hmac-sha512“.