Issue Let's Encrypt SSL Certificates using DNS Validation

This guide will cover how to issue SSL certificates using Let's Encrypt by way of the dns-01 challenge. To use the dns-01 challenge when issuing SSL certificates from Let's Encrypt, a couple extra steps are required to support the process.

Issue Let's Encrypt SSL Certificates using DNS Validation
Photo by Kvalifik / Unsplash
To learn how to install Let's Encrypt and handle SSL certificates after issuance please see the guide Issue & Renew Let's Encrypt SSL Certificates for Ansible Automation Platform 2.

To use the dns-01 challenge when issuing SSL certificates from Let's Encrypt, a couple extra steps are required to support the process.  A Python script will need to be downloaded to be used for the dns-01 challenge and certificates will need to be issued using a few extra arguments to ensure it is the primary challenge over http-01.

Download the Python script for certbot support of dns-01 challenge

Certbot doesn't come with a way to handle DNS validation for issuing SSL certificates through Let's Encrypt.  Luckily, there is a GitHub project at https://github.com/joohoi/acme-dns-certbot-joohoi available that can take care of it for Certbot.

wget https://github.com/joohoi/acme-dns-certbot-joohoi/raw/master/acme-dns-auth.py

Make the Python script executable

chmod +x acme-dns-auth.py

Change the Python script for Python3 support

Using your favorite text editor, edit the acme-dns-auth.py file and add a 3 to the end of python on the first line in the script.

#!/usr/bin/env python3
. . . .
acme-dns-auth.py

Move the script to Certbot's Let's Encrypt directory

sudo mv acme-dns-auth.py /etc/letsencrypt/

Issue an SSL Certificate using dns-01 challenge

For the dns-01 challenge to become the primary challenge method, at least one (1) certificate needs to be issued.  We can start this by running Certbot and forcing it to issue a certificate using DNS validation.  This will run the acme-dns-certbot Python script and trigger the initial setup process.

sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d aap.example.com

In the above command, the --manual argument is used to disable the automated integration features of Certbot.  This is similar to using the --standalone argument when issuing a certificate in the http-01 challenge above.

The argument --manual-auth-hook is how we tell Certbot where to find the Python script that will handle our --preferred-challenges which is dns.  This also sets dns as the preferred challenge in all future renewals.

Since the dns-01 challenge requires a CNAME record to be set in the DNS, we will need a way to have Certbot pause so that it can be completed.  To do this, the argument --debug-challenges is provided.  Without the argument, Certbot wouldn't pause and there would be no time given to make the required DNS changes.

In the command above, the -d argument is provided once for the domain aap.example.com.  More than one (1) domain is supported by including additional -d arguments.  Alternatively, wildcard certificates are supported as a value to the -d argument.  I do not recommend this practice, but if you do want to set it up, you'll need to escape the asterisk with a backslash like this -d \*.aap.example.com.

Once the command is sent, you'll receive a response and pause from the acme-dns-auth.py script.

...
Output from acme-dns-auth.py:
Please add the following CNAME record to your main DNS zone:
_acme-challenge.aap.example.com CNAME a15ce5b2-f169-4c91-97bf-09a5454a88f6.auth.acme-dns.io.

Waiting for verification...
...
Output

Add CNAME record to main DNS zone

You'll need to have knowledge and access to your main DNS zone to configure the CNAME record based on the output given in the previous step.  It is recommended to set the TTL of the CNAME record to 300 seconds.  Once you have completed this step, press ENTER to validate the certificate request and complete the issuance process.

...
Congratulations! Your certificate and change have been saved at:
/etc/letsencrypt/live/aap.example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/aap.example.com/privkey.pem
...
Output