Another niche one.
I have some webservers for which I want a valid, not self-signed, TLS certificate.
Simple, thanks to Let’s Encrypt.
But I do not want to expose the web server to the world most of the time.
I also want my TLS certs renewed automatically (part of the Let’s Encrypt design, to encourage good hygiene), so a solution which requires me to log in to change anything is not an option.
So what I need is an ability for Let’s Encrypt to automatically reconfigure my firewalls to allow access for the duration of a renewal attempt, and then close that access afterwards.
Fortunately, this is eminently achievable, bringing in a few bits:
certbotfor the Let’s Encrypt renewals
- bash scripts for pre and post renewal-hooks for the certbot renewals
- an application profile for
ufwto go in the bash script
- a curl command for the network firewall
Working out the firewall config changes
There are two firewalls I need to configure: the machine’s local firewall (
ufw), and the network-level firewall.
Each needs to (temporarily) allow tcp on ports 80 and 443.
ufw / local firewall
To automate changes to ufw, I created a ufw application profile:
[letsencrypt] title=access to the world for Let's Encrypt description=access to the world for Let's Encrypt ports=80/tcp|443/tcp
This goes in
I can trigger this using
ufw from the command line:
ufw allow letsencrypt
to enable it.
ufw delete allow letsencrypt
to delete it.
My network firewall (a FireBrick) supports profiles, and those profiles can be adjusted by a suitably-privileged user, via
So what I needed was a profile which was a simple toggle (on/off), which I applied to a firewall rule permitting 80/443 tcp.
Let’s Encrypt renewal-hooks
You can run scripts automatically when Let’s Encrypt attempts a renewal, by putting them in the relevant directory.
For me, this is
/etc/letsencrypt/renewal-hooks, and either
pre for scripts to run before renewal, and
post to run afterwards (whether successful or not).
pre, I have a bash script which contains just the
ufw allow letsencrypt command, and a
curl toggle for the network firewall.
post, it runs
ufw delete allow letsencrypt and the
curl toggle to close the network firewall.
certbot has a convenient testing mechanism, to check it all works from a Let’s Encrypt perspective:
certbot renewal --dry-run
This mimics a renewal, including the pre- and post- hooks, but without actually doing a renewal.
(In addition, it’s worth checking the ufw rules afterwards, to make sure that what you expect to be deleted is deleted. You might also run the post script as a cronjob, just as a backup, although there’s a risk it could interfere with a genuine Let’s Encrypt renewal.)