Automating Letsencrypt Wildcard Certificate renewal with Mail in a Box.

I use letsencrypt, a fantastic free service to secure my websites. However, like many people I have multiple sub-domains for my blogs, gitea and whatever else I fancy spinning up. These are all hosted on a separate box, not my MIAB box. So when Letsencrypt announced their wildcard certificate I jumped on board.
The only problem I had with wildcard certificates were the extra steps required automate the whole process. The issue was that Letsencrypt (or certibot, the program that does the work) required txt records to be updated in publicly available DNS records.
As I also use Mail in a Box for my public DNS and email I had to write some scripts and entries in crontab to automate the renewal process. Thankfully Mail-in-a-box has an API for doing exactly this.

Notes and Caveats:

  • I’ve seen other blog entries that do the same thing (minus the automation) for a single certificate. However when I generated my certs some time ago, I followed these instructions. As such my cleanup.sh script did not work as expected, so run it separately, not via the –manual-cleanup-hook call.
  • Read the documentation if you have problems: https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks
  • If you figure out how to make the cleanup script work as a hook – please let me know in the comments 😉
  • I assume you already have certibot/letsencrypt installed
  • You will need to substitute your credentials in the scripts – I have a specific account I use for just this, so my personal email/admin account isn’t compromised with the password stored in plain text.
  • Make sure your scripts have the executable bit set (chmod +x).
  • My crontab entries will email root, which is aliased out, to my personal email address.
  • Cron jobs (see comments in scripts) will run at midnight and 5 minutes past midnight respectively, every 5 days.

The Scripts:

These are super basic:
/root/renewal.sh

#!/bin/bash
#add to crontab like this:
#0 0 */5 * * /root/renewal.sh | mail s "Lets Encrypt Certificate Renewal" root >/dev/null 2>&1
sudo certbot certonly -n --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory --manual --manual-authhook ./authenticator.sh --preferred-challenges dns -d "dom.ain, *.dom.ain"

/root/authenticator.sh

 #!/bin/bash

curl -s -X PUT -d "$CERTBOT_VALIDATION" --user user@dom.ain:<Password>  https://<your.maib.url>/admin/dns/custom/_acme-challenge.dom.ain/txt 

/root/cleanup.sh

#!/bin/bash
#Add to crontab:
#5 0 */5 * * /root/renewal.sh | mail -s "Lets Encrypt Certificate Renewal" root >/dev/null 2>&1
# get the txt record
TOREMOVE=`curl -s -X GET --user user@dom.ain:<password> https://<your_MIAB_Server>/admin/dns/custom/_acme-dom.ian/txt  | grep "value" | awk '{print $2}'| sed 's/"//g'`
echo "removing $TOREMOVE"
curl -s -X DELETE -d "$TOREMOVE" --user user@dom.ain:<password> https://<your_MIAB_Server>/admin/dns/custom/_acme-dom.ian/txt 
service apache2 restart

Finally, if you want to check the certificate run:

certbot certificates