Certbot not working properly with DNS-01


#1

Certbot not working properly with DNS-01

I was previously using the TLS-SNI-01 authentication method for my mail server — certbot 0.28.0 —, but due to the deprecation I decided to switch to the DNS-01 method, since I have a running bind9 installation on my server, with Ubuntu 16.04.5 LTS.

To do that I installed the certbot-dns-rfc2136 package, created a HMAC-SHA512 key, updated bind9 for the _acme-challenge., and finally created the credentials file for the rfc2136 plugin:

dns_rfc2136_server = 78.47.161.24
dns_rfc2136_name = <NAME>
dns_rfc2136_secret = <SECRET_KEY>
dns_rfc2136_algorithm = HMAC-SHA512

With everthing configured I tested the configuration with a dry run: certbot certonly --dry-run --dns-rfc2136 --dns-rfc2136-credentials /root/certbot-rfc2136.ini --dns-rfc2136-propagation-seconds 5 -d mail.skydubh.com:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-rfc2136, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for mail.skydubh.com
Waiting 5 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - The dry run was successful.

At this point I generated the certificate without the --dry-run and the problems started. Certbot creates an empty configuration file:

# ls -al /etc/letsencrypt/renewal
-rw-r--r-- 1 root root    0 Jan 27 16:49 mail.skydubh.com.conf

The renew fails due to the empty configuration file:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/certbot/renewal.py", line 64, in _reconstitute
    renewal_candidate = storage.RenewableCert(full_path, config)
  File "/usr/lib/python3/dist-packages/certbot/storage.py", line 441, in __init__
    "file reference".format(self.configfile))
certbot.errors.CertStorageError: renewal config file {} is missing a required file reference
Renewal configuration file /etc/letsencrypt/renewal/mail.skydubh.com.conf is broken. Skipping.

Manually passing the --dns-rfc2136-* parameters doesn’t help either for the same reason.

I started considering using certbot-auto to have an up to date version that wasn’t provided through packages, but I’ve been unable to make it use python3 (I’ve tried exporting USE_PYTHON_3=1 to no avail), and given that the only package available is python3-certbot-dns-rfc2136, certbot-auto complains about not finding the dns-rfc2136 plugin: The requested dns-rfc2136 plugin does not appear to be installed.

I’m out of ideas, how do I get out of this alive?


#2

I finally managed to work around the issue through certbot-auto, I’m gonna report how in case someone else finds itself in the same situation. In order to be as clear as possible:

  1. I have the initialisation file /root/certbot-rfc2136.ini, with the content displayed in the post above.
  2. I have downloaded the certbot-auto inside /root.
  3. I have already installed python3-certbot-dns-rfc2136 on my ubuntu server.

Note that if you want to just manually create the missing configuration file, you can skip to the end of this post to find the proper content required for dns-rfc2136 to work, without installing anything else.


If you mistakenly bootstrapped certbot-auto with py2.7 (like me) you want to remove the /opt/eff.org/certbot/venv/ directory with all of its content. After that is done we can prepare for the new boostrap. To do that we need to create the virtual environment using python 3, and then we need to copy the required python libraries into the virtual environment, so that certbot-auto can properly parse dns-rfc2136 requests:

# apt-get install python3-dev python3-venv
# export LE_PYTHON=python3
# ./certbot-auto --version
<a bunch of package installation>
certbot 0.30.2
# cd /opt/eff.org/certbot/venv/lib/python<version>/site-packages/
# cp -R /usr/lib/python3/dist-packages/certbot_dns_* .
# cp -R /usr/lib/python3/dist-packages/dns .
# cd /root/
# ./certbot-auto certonly --dns-rfc2136 --dns-rfc2136-credentials /root/certbot-rfc2136.ini --dns-rfc2136-propagation-seconds 5 -d <server_name>
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-rfc2136, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for <server_name>
Waiting 5 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/<server_name>/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/<server_name>/privkey.pem
   Your cert will expire on 2019-04-27. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

At this point, certbot-auto has created the configuration file properly, and this is the content for /etc/letsencrypt/renewal/<server_name>.conf:

# renew_before_expiry = 30 days
version = 0.30.2
archive_dir = /etc/letsencrypt/archive/<server_name>
cert = /etc/letsencrypt/live/<server_name>/cert.pem
privkey = /etc/letsencrypt/live/<server_name>/privkey.pem
chain = /etc/letsencrypt/live/<server_name>/chain.pem
fullchain = /etc/letsencrypt/live/<server_name>/fullchain.pem

# Options used in the renewal process
[renewalparams]
dns_rfc2136_propagation_seconds = 5
dns_rfc2136_credentials = /root/certbot-rfc2136.ini
account = <accountId>
server = https://acme-v02.api.letsencrypt.org/directory
authenticator = dns-rfc2136

certbot renew will now work properly, at least with version 0.28.0, so you can safely remove certbot-auto and the additional dependencies, should you desire.