Using Let’s Encrypt / EFF’s CertBot with NGINX in Docker

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 \
                [email protected]
}

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;

2 thoughts on “Using Let’s Encrypt / EFF’s CertBot with NGINX in Docker”

  1. Thanks, this was rather helpful in getting an nginx server up and running. A few comments and a question:

    Comment: You probably don’t need the “-v /docker/storage/webfrontend/letsencrypt/lib:/var/lib/letsencrypt \” line since you are using –webroot

    Question: How do you automate the creation of the new config containing the ssl_certificate and ssl_certificate_key? Having them in from the start messes with the Nginx server, and the best solution I can think of is to have a pure HTTP config template prior to installing the Docker compose, and then copy over one containing these two lines prior to running “docker-compose up”. Is there an easier solution”

    Thanks!

    1. fwiw, on automation, I came to the same conclusion. I just patched the configuration files (which, in my first case were controlled by gitlab) and installed certbot into the container from outside.

      I still don’t have a great approach to renewing certificates, however, other than running cron in the containing host.

      It’s also worth noting that EFF’s view is that certificates should be persisted until they expire. My initial approach was to discard them, but I soon ran out after recreating the container a few times.

Leave a Reply

Your email address will not be published. Required fields are marked *