Matt Howlett

Matt Howlett

Every Blog Should Have a Tagline

Setting up HTTPS with LetsEncrypt, Docker and Nginx

2016-10-22

Here's some quick notes on how to enable HTTPS on your nginx powered or reverse-proxied websites using letsencrypt and docker.

This post is a bit verbose, but the process is really simple.

The official docs recommend not using the docker image, but I prefer doing it this way because I have a strong preference for avoiding installation of software outside of docker containers.

First, add the following location to your existing nginx server configuration:

location /.well-known/acme-challenge {
  default_type text/plain;
  root /tmp/letsencrypt;
}

This allows the letsencrypt client to verify your control over the domain. Assuming you're running nginx inside a docker container, you'll also need to mount the /tmp/letsencrypt folder using -v /tmp/letsencrypt:/tmp/letsencrypt

Now use the letsencrypt docker image and webroot plugin to perform a certificate request:

docker run -it --rm --name letsencrypt -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" -v /tmp/letsencrypt:/tmp/letsencrypt quay.io/letsencrypt/letsencrypt:latest auth -a webroot --webroot-path /tmp/letsencrypt -d <domain>

where <domain> is your domain name (including the www subdomain if you're using that).

your certificates are ready already(!) and can be found in:

/etc/letsencrypt/live/<domain>

Now add the following to your nginx server config to enable HTTPS:

server_name <domain>;
ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;
listen 443 ssl;

Assuming you're using nginx within a docker container, you'll need to mount /etc/letsencrypt using -v /etc/letsencrypt:/etc/letsencrypt

You might want to redirect HTTP traffic by adding the following to your nginx config:

server {
  listen 80;
  server_name <domain>;
  rewrite ^(.*) https://<domain>$1 permanent;
}

LetsEncrypt certificates need to be renewed every 90 days. This can be done using the same command as used to issue them with the addition of the --renew-by-default flag. You could make a cron job for this:

crontab -e -u root
0 0 */60 * * docker run -it --rm --name letsencrypt -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" -v /tmp/letsencrypt:/tmp/letsencrypt quay.io/letsencrypt/letsencrypt:latest auth -a webroot --webroot-path /tmp/letsencrypt -d <domain> --renew-by-default