The wonderful Let's Encrypt makes it easy to easy to generate and install SSL certificates for free using the certbot ACME client on a webserver. But what if, like me, you want to generate and install your certs on a server behind a firewall so that you can use subdomains in your home network while keeping that network private.
Yep, they make that easy too because certbot supports dns challenge as a method of verifying your ownership of a domain and provides dns plugins for every major DNS provider.
How DNS challenge works with certbot
The certbot docs provide a much better explanation of this than I ever could but TLDR:
- Certbot requests a certificate from the Let's Encrypt servers
- Let's Encrypt servers return challenge contents
- Plugin creates a TXT DNS record containing the challenge contents
- Let's Encrypt servers validate the TXT DNS record
- Let's Encrypt servers issue certificate
Let's use docker
In my case I use Cloudflare as my DNS provider and I'm going to generate the cert on my trusty Synology NAS. Now I could manually install certbot, it's dependencies and the Cloudflare plugin, but the Synology has Docker installed and there's a Docker image for the Cloudflare plugin so that's much simpler.
The docker image needs to match a couple of letsencrypt volumes inside /var/lib and /etc/ so we'll start by creating them.
sudo mkdir /etc/letsencrypt sudo mkdir /var/lib/letsencrypt
Set up Cloudflare credentials
To enable certbot to create TXT records via the Cloudflare API we'll need to create an API token via the cloudflare dashboard. We choose to create a token and select the
Edit zone DNS template and create the token for my domain.
Now we have the token let's create a
cloudflare.ini file that certbot will read the token from.
sudo vi /etc/letsencrypt/cloudflare.ini
The file contents should have the following format.
Now we can run the docker container passing in the location of the
ini file containing the api token and the name of the domain to generate a certificate for. I'm using
*.admcpr.com to generate a wildcard cert so I can use this cert for lots of different subdomains in my local network.
sudo docker run -it --rm --name certbot \ -v "/etc/letsencrypt:/etc/letsencrypt" \ -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ certbot/dns-cloudflare \ certonly --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \ -d *.admcpr.com
Once this command completes the cert can be found in
$domain is the name of the domain the cert was generated for, so for me that's
/etc/letsencrypt/live/admcpr.com. Now we can grab that cert and install it wherever we want to have SSL on a subdomain.
Let's Encrypt certs are valid for 3 months so I'll need to setup some way to automate renewal and find a more secure place to store the Cloudflare API key.