Automating Let’s Encrypt Certificate Renewal with DNS Challenge
Renew Let’s encrypt certificates using DNS challenge type in fully automated way wrapping certbot cli.
In some cases Let’s Encrypt offers only one way to renew a certificate, using DNS-01 challenge. It is relatively easy to automate this process with certbot by its plugins, if you use popular DNS service providers. However for less popular providers you might need to create a wrapper over certbot that helps renew certificates automatically with one button click.
When you want to renew your SSL certificate from Let’s encrypt, it can offer three types of challenges: HTTP-01, DNS-01, and TLS-ALPN — 01 (not supported by certbot). But if you want to renew wildcard certificate, you have only DNS-01 option. It provides you with a special token that you need to put in TXT record of your domain, so that Let’s Encrypt can verify it.
The problem is that typically your DNS service provider has web interface to manage your DNS zone, and you are lucky if it has any kind of API, but most likely it doesn’t.
To make it simpler Let’s Encrypt asks you to update TXT record for certain subdomain, which is _acme-challenge (e.g. _acme-challenge.example.com). And it gives you some kind of hope to script it.
Now let’s see what is NS record type in DNS world. This record allows you to delegate authority for certain domain (or subdomain) to external DNS server. And nothing prevents you from making NS record pointing to a small VM in your infrastructure.
If you followed me all this time, you could already get the idea. Firstly you configure NS record for _acme-challenge.example.com subdomain to the local server where you run certbot, then parse output from it, update local DNS server, and finally Let’s Encrypt verifies the TXT record.
I am omitting some obvious steps and make the diagram oversimplified just to give you the idea of how it works.
- Certbot requests for certificate renewal
- Let’s Encrypt sends DNS challenge with TXT value
- Automation on the server parses certbot output and updates local DNS server configuration with the TXT value
- As soon as certbot confirms the update, let’s encrypt verifies the TXT record of _acme-challenge.example.com
5. Our DNS provider has preconfigured NS record that delegates _acme-challenge subdomain to our server
6. Our server responds with TXT record that was configured on step 3
7. Once Let’s Encrypt receives TXT value and verifies it, it withdraws a new certificate
So how does the automation on server look like. Firstly there needs to be some software installed. I am going to use Ubuntu 20.04 server.
certbot has following output, firstly it asks you if you are ok with logging your IP. And that is the first answer we are going answer with `expect`.
`expect` is a cli tool that interacts with interactive programs according to a script. The script that answers certbot’s question looks like this
Essentially it waits for “(Y)es/(N)o: “ dialog and answers with Y. Then when it sees “Press Enter to Continue” it waits for 10 seconds. In the meantime another script parses certbot output, finds a TXT value and updates dnsmasq configuration. Typically 10 seconds is more than enough for that.
To let the script parse output of certbot, we are running the expect script redirecting its output to a file.
The following two shell functions do the dirty job. They parse certbot’s output, find a TXT token and update the dnsmasq configuration.
This is it, now you only need to take care about saving certificates and put them in the right place.