Blog

How to renew WildCard SSL using LetsEncrypt Certbot updating DNS records automatically without interaction?

As LetsEncrypt does not allow webroot or any other verification method for renewing WildCard SSL certificates like *.domain1.com, for a client I needed to renew LetsEncrypt WildCard SSL automatically without requiring any manual interaction.

It is simple but took some time to figure out. The most important certbot parameter here is manual-auth-hook.

The client’s domain was hosted on Oracle and Oracle Infrastructure API requires a complicated authentication. So, I used Cloudflare for that. I did not move the domain to Cloudflare but I just added a CNAME for the domain on Oracle which pointed to the TXT record on Cloudflare.

So, let’s say these are the 2 domains: one on Oracle and other one on Cloudflare.
domain1.com (Oracle) – The main domain.
domain2.com (Cloudflare) – The helper domain.

– To start with, I added a TXT DNS record on Cloudflare for domain2.com with name _acme-challenge-domain1-com.domain2.com and value “anything”.
– Next, I added CNAME DNS record on Oracle for domain1.com with name _acme-challenge.domain1.com and value _acme-challenge-domain1-com.domain2.com.

Now, whenever certbot will try to look for _acme-challenge.domain1.com, the DNS servers will serve TXT record value from _acme-challenge-domain1-com.domain2.com.

Then I had to look into Cloudflare API and finally made DNS updating work using curl with this command:

curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/DNS_RECORD_ID" \
-H "Content-Type:application/json" \
-H "Authorization: Bearer YOUR_CLOUDFLARE_ACCESS_TOKEN" \
-d '{"type":"TXT", "name": "_acme-challenge-domain1-com", "proxied": false, "content": "ANYTHING"}'

You can first list zones for finding zone id using: https://api.cloudflare.com/client/v4/zones

And, then find DNS record id using: https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records

After this I had to write a bash script to automate updating of DNS record to Cloudflare.

The script looked like this:

#!/bin/bash
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/DNS_RECORD_ID" \
-H "Content-Type:application/json" \
-H "Authorization: Bearer YOUR_CLOUDFLARE_ACCESS_TOKEN" \
-d '{"type":"TXT", "name": "_acme-challenge-domain1-com", "proxied": false, "content": "'$CERTBOT_VALIDATION'"}'
sleep 10
echo "DNS record updated."

Please note that we need to pause script for 10 seconds after updating DNS record to make sure that the DNS record was updated successfully yo Cloudflare.

I saved the above script at /root/certbot/auth.sh and gave run permission using chmod +x

I used this command to check domain renewal: certbot renew --cert-name domain1.com --manual --dry-run --preferred-challenges=dns --agree-tos --manual-public-ip-logging-ok --keep-until-expiring --manual-auth-hook /root/certbot/auth.sh

Please note I used --dry-run first to check if everything was ok.
If the above command says that the domain was renewed successfully, then we are all good and now we just need to run the command without --dry-run.

certbot renew --cert-name domain1.com --manual --preferred-challenges=dns --agree-tos --manual-public-ip-logging-ok --keep-until-expiring --manual-auth-hook /root/certbot/auth.sh

Hope this helps someone.

Leave a Reply

Your email address will not be published. Required fields are marked *