In my last post, I talked a little bit about the magical ease-of-use that comes from Jason Wilder's nginx-proxy Docker container, which I use to route subdomains on sequentialread.com.

Well, today I finally got around to enabling HTTPS for the site using letsencrypt. letsencrypt is a really cool initiative to make trusted SSL certificates available for free. And not just free as in free beer, but free as in Libre as well.

I was shocked at how easy the process was. Here's exactly how it went down. First, I followed the instructions from the getting started page on letsencrypt.

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto --help

Then I decided I would use the certonly method and --standalone option because my web server configuration was complicated, and their plugins, for example for apache running on bare metal, didn't apply to my situation.

So I temporarily stopped my http server and crafted a long command line including each of my public subdomains:

 ./letsencrypt-auto certonly --standalone -d sequentialread.com -d git.sequentialread.com -d comments.sequentialread.com -d www.sequentialread.com -d www.git.sequentialread.com -d www.comments.sequentialread.com

At first, the tool failed: It explained that the letsencrypt server was unable to reach sequentialread.com on port 443. At first I was worried, but then remembered that I was behind a NAT, and I had forgotten to forward port 443 on my router.

After forwarding the port and retrying, the tool informed me that it had succeeded and dropped some certificates into the /etc/letsencrypt/live/sequentialread.com directory. I checked to see what was there and saw:

ls /etc/letsencrypt/live/sequentialread.com
cert.pem  chain.pem  fullchain.pem  privkey.pem

Then I checked the documentation for jwilder/nginx-proxy regarding SSL and saw that the tool expected certificates and private keys to appear in a certain place, either named according to the subdomain or via a CERT_NAME environment variable. So I put CERT_NAME: letsencrypt on all of my containers that are served publicly, mounted the /dockerdata/nginx/certs directory at the correct place inside the jwilder/nginx-proxy container, copied the files according to what nginx-proxy expects, and restarted docker-compose:

cp /etc/letsencrypt/live/sequentialread.com/fullchain.pem /dockerdata/nginx/certs/letsencrypt.crt
cp /etc/letsencrypt/live/sequentialread.com/privkey.pem /dockerdata/nginx/certs/letsencrypt.key
docker-compose -f /compose/docker-compose.yml stop
docker-compose -f /compose/docker-compose.yml up -d

I did run into a minor snag, where docker couldn't mount the certs volume without re-creating the jwilder/nginx-proxy container, but after that, it worked right away.

I was completely blown away by how easy it was. The whole process only took about a half an hour, while I was expecting to be debugging the setup all evening, or end up having to revert to a hard-coded nginx configuration.

I wouldn't use this setup without giving it more scrutiny if I was handling credit card data or other sensitive information, but for ease-of-use, it can't be beat.

Comments