Matt Howlett

Matt Howlett

Software Development and Mathematics Blog

Setting up HTTPS with LetsEncrypt, Docker and Nginx


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 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:


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 auth -a webroot --webroot-path /tmp/letsencrypt -d <domain> --renew-by-default