Technology Solutions for Everyday Folks

Certbot in Manual Mode with Script Hooks

If you've been following along in the mini series, I've gone over the details of using Certbot in manual mode, then bolting some simple scripts together to improve the process of generating and managing certs, all done with a bit of magic thanks to our old friend key authentication.

In the final installment, I'll go over the process of how I used manual authentication and cleanup hooks with Certbot to more or less fully-automate the domain validation process.

Since I can't automate the copy/paste of certificates into the cPanel interface, this is a close second-place in the automation world for me, and something that I am super stoked to have worked through and figured out. As I'd mentioned in the past, the Certbot documentation is super thorough, but very overwhelming. I had to really understand my pain points for each iteration, and then try to figure out how to improve around those pain points.

Manual Hooks For The Win!

I started reading some of the documentation and stumbled across the Pre and Post Validation Hooks section. I'd seen this information before, but had mistakenly understood it to function as something else, so I didn't think it'd apply. How wrong I was...

The Pre Validation Hook (Auth)

Out of the gate I was most interested in the auth (pre) hook since it was the key to really buttoning up the domain validation files. Since I have a remote host, I had to make a minor modification to the example script, as illustrated:

#!/bin/bash
echo $CERTBOT_VALIDATION > ./validation/$CERTBOT_TOKEN
scp -i ~/.ssh/super_private_key ./validation/$CERTBOT_TOKEN
       user@hostname:/path/to/.well-known/acme-challenge/
ssh -i ~/.ssh/super_private_key user@hostname chmod 664 
       /path/to/.well-known/acme-challenge/$CERTBOT_TOKEN

The aforementioned script is set up as auth-host.sh in a local directory ./auth/ where host is the specific hostname in scope. This allows me to customize the paths for various hosts as necessary.

What this script does is create the file with its proper name and data in the ./validation/ directory, then copies said file to the remote host. Since I'm running this all in the Windows filesystem (though via WSL), there are some wonky file permissions carried across in the copy, so I quickly reset those to a remote host side standard 664. Admittedly this is an unnecessary modification, since the files are all transient anyway and will be removed in the cleanup hook.

The Post Validation Hook (Cleanup)

To keep me out of the remote host fully in this process, having a cleanup hook remove the domain validation files would be awesome, so I went through with minor modification to the example script:

#!/bin/bash
ssh -i ~/.ssh/super_private_key user@hostname rm -f 
       /path/to/.well-known/acme-challenge/$CERTBOT_TOKEN
rm -f ./validation/$CERTBOT_TOKEN

This script is set up as cleanup-host.sh in a local directory ./cleanup/ where host is the specific hostname in scope, just like the auth example above.

What this script does is remotely and locally removes the domain validation file once the certificate is issued.

Bolting It Together

A few minor but powerful modifications to the existing certbot-superdomain.sh script, and this is all set:

#!/bin/bash
certbot certonly --manual --manual-public-ip-logging-ok 
          --preferred-challenges=http --manual-auth-hook ./auth/auth-host.sh 
          --manual-cleanup-hook ./cleanup/cleanup-host.sh
          -d superdomain.net -d www.superdomain.net
read -n1 -r -s -p "Press any key to load certificate...`echo $'\r\n\r\n'`"
more /etc/letsencrypt/live/superdomain.net/cert.pem
read -n1 -r -s -p "Press any key to load private key...`echo $'\r\n\r\n'`"
more /etc/letsencrypt/live/superdomain.net/privkey.pem
read -n1 -r -s -p "Press any key to end certificate renewal process...`echo $'\r\n\r\n'`"

A few key additions:

  • --preferred-challenges=http which forces Certbot to use DV files
  • --manual-auth-hook ./auth/auth-host.sh, the pointer to my custom auth file
  • --manual-cleanup-hook ./cleanup/cleanup-host.sh, the pointer to my custom cleanup file

And It's Automated!!

Now, by invoking/running sudo bash ./certbot-superdomain.sh the entire certificate generation/renewal and domain validation is handled more or less automatically. It is only the copy/paste of the CRT and KEY files to cPanel left, which is more nicely handled with the script pauses.

I have created a repo with the basics identified above; feel free to use and modify/expand!

Since I'm doing this on a quarterly-ish basis, or when I get the Let's Encrypt expiration notice (this is why Certbot initially needs your email address), I am prepared to spend a few minutes going through the process. Ideally it'd be fully automatic, but I will take what I can get.

I am Most Pleased with the improvements I've made based on my own pain and suffering, though. But what I will enjoy most as these renewals come due is the fact that I've got a simple way to run a bunch of these all together (a super script), that will ideally make this a five-minute process for a couple dozen domains. That's the power of automation.