I’m using NGINX in a Docker Container as a front-end HTTP(s) Webserver, performing SSL termination and proxying incoming requests to various other Docker Containers and VMs. Now that I’ve switched my certificates to Let’s Encrypt, I wondered how to integrate EFF’s CertBot (which is recommended by Let’s Encrypt) with my setup. Here’s how I did it.

First, I’ve added two new volumes to my web-front-end’s Docker Compose File:

version: '2'
services:
  webfrontend:
    container_name: webfrontend
    [...]
    volumes:
      - "/etc/localtime:/etc/localtime:ro"
      - "/etc/timezone:/etc/timezone:ro"
      - "/docker/storage/webfrontend/letsencrypt/www:/var/www/letsencrypt"
      - "/docker/storage/webfrontend/letsencrypt/etc:/etc/letsencrypt"

Next, I’ve added the following location block to each of my virtual hosts:

location /.well-known/ {
    alias /var/www/letsencrypt/;
}

I’m using the palobo/certbot Docker Image to create the certificates, using this shell script:

#!/bin/sh

docker pull palobo/certbot

GetCert() {
        docker run -it \
                --rm \
                -v /docker/storage/webfrontend/letsencrypt/etc:/etc/letsencrypt \
                -v /docker/storage/webfrontend/letsencrypt/lib:/var/lib/letsencrypt \
                -v /docker/storage/webfrontend/letsencrypt/www:/var/www/.well-known \
                palobo/certbot -t certonly --webroot -w /var/www \
                --keep-until-expiring \
                $@
}

echo "Getting certificates..."
GetCert -d www.mydomain.com -d mydomain.com
GetCert -d somedomain.net

echo "Restarting Web Frontend..."
cd /docker/containers/webfrontend
docker-compose down
docker-compose up -d
cd -

echo "Done"

The script starts CertBot in a Docker Container for each requested certificate. Because the /etc/letsencrypt and the /var/www/.well-known directory is also used by my NGINX front-end Container (see above), these steps can be performed by the script:

  1. Using the webroot plugin, a random file is created under the /.well-known/acme-challenge/ directory.
  2. Let’s Encrypt can access and verify this file as the folder is aliased using the Location blocks in the NGINX config.
  3. The generated private key and public certificate is placed in /etc/letsencrypt/, which is in turn a volume for the NGINX web-frontend.

You can use the generated certificates by adding these two lines to your NGINX vhost config:

ssl_certificate     /etc/letsencrypt/live/www.mydomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.mydomain.com/privkey.pem;