Setup Let’s Encrypt certificate with Nginx, Certbot and Docker
Background
Let’s Encrypt
is certificate Authority (CA) which provides free SSL certificates. By default these certificates expires in 90 days. We can renew the certificates before expiring and continue to using them to have HTTPS services. There is a Certbot
client which can used to automate the certificate obtain and renewals. In this post I’m gonna discuss about automating Let’s Encrypt certificate obtain and renewal with Nginx
and Docker
by using the Certbot
tool. All the source codes which related to this post available in gitlab. Please clone the repo and continue the post.
Scenario
I have a domain named climguards.com
. The services which related to this domain have configured in DigitalOcean
droplet. I’m gonna obtain a certificate for this domain from Let’s Encrypt. Following are the steps I have followed to obtain and configure the Let’s Encrypt certificates in the DigitalOcean
droplet which related with climguards.com
domain.
Dockerize Nginx with Certbot
First I have Dockerized Nginx
with Certbot
. Following is the Dockerfile
I have used. I have run Nginx
and Certbot
in single Docker container. If want we can run them on separate Docker containers as well.
When issuing the certificates for a domain, Let’s Encrypt verifies the domain name and ownership via ACME challenge
. To have this I need to update Nginx configuration with a server node listening to port 80
and serving the .well-known
folder where the acme-challenge file will be dropped. Following is the Nginx configuration file I have created with this configurations.
I have built the Nginx Docker image with this configuration file and pushed to docker hub. To obtain certificates I run the Nginx docker in DigitalOcean droplet. Following is the docker-compose.yml
file I have used to run the Nginx. Nginx container can be started with docker-compose up -d nginx
command. In the docker-compose I have defined the Docker volume for the /etc/letsencrypt
directory where stores the Let’s Encrypt certificate files. Before run the Nginx please make sure port 80
and port 443
are open in the firewall.
Obtain Certificate
The Certbot
command resides inside the Nginx docker container. To obtain certificate I have connected to Nginx docker container and issued following Certbot command. Before do that, you need to be aware that Let’s Encrypt has rate limits. Most notably, there’s a limit of 20 issued certificates per 7 days. So if you exceeded 20 requests and are having a problem with generating your certificate for whatever reason, you could run into trouble. Therefore, it’s always wise to run your commands with a --staging
parameter which will allow you to test if your commands will execute properly before running the actual commands. If everything runs well the certificate will be downloaded into /etc/letsencrypt/live/climguards.com/
directory inside the Nginx docker container. Since I have a Docker volume for /etc/letsencrypt/
directory, the certificates will be available in host machine as well.
If the staging command executed successfully, I can execute the command to get a live certificate. In this command I have replaced the --staging
flag with the --force-renewal
flag, which will tell Certbot that I want to request a new certificate with the same domains as an existing certificate.
In here I have manually enter the Certbot command inside Nginx docker container to obtain the Let’s Encrypt certificates. Instead of obtaining the certificates by manually entering the Certbot commands we can automate them via a shell script as well. In a coming post I will discuss about it. For now you can find more details from this blog post.
Nginx with SSL
Now I can enable the SSL in Nginx with using the Let’s Encrypt certificates. Following is the climguards.com
Nginx config file with SSL configurations. It contains server entries for both HTTP
and HTTPS
. The other thing to notice is I have defined a proxy_pass
reverse proxy entry to serve an internal API via Nginx. Read more about reverse proxy configuration of Nginx from this post.
Following is the new Dockerfile to dockerize the SSL enabled Nginx. It adds the SSL certificates in the /etc/letsencrypt/live/climguards.com/
directory into Nginx Docker image. These certificates used in the climguards.com
Nginx config file. I can built and run the new Nginx Docker with same docker-compose.yml
which mentioned above.
Renew Certificates
As mentioned about the Let’s Encrypt certificates will expires after 90 days. We can renew the certificates before expiring by using the certbot renew --dry-run
command. Certbot renew command can be run with --dry-run
option to test the script before using in the production. To automate the certificate renewal I have added this Certbot renew command into Crontab
inside the Nginx docker. This Crontab command will run every night at 23:00
. If the certificates are due for renewal, the certificates will renew. Following is the docker-entrypoint.sh
which I have used to add Certbot renew command into Crontab while starting the Nginx.
Reference
- https://delattreconsulting.com/2020/02/lets-encrypt-ssl-certificate-through-certbot-for-nginx-in-a-docker-environment/
- https://www.digitalocean.com/community/tutorials/how-to-secure-a-containerized-node-js-application-with-nginx-let-s-encrypt-and-docker-compose
- https://www.humankode.com/ssl/how-to-set-up-free-ssl-certificates-from-lets-encrypt-using-docker-and-nginx
- https://geko.cloud/nginx-and-ssl-with-certbot-in-docker-alpine/
- https://www.cloudbooklet.com/how-to-install-nginx-and-lets-encrypt-with-docker-ubuntu-20-04/
- https://ilhicas.com/2019/03/02/Nginx-Letsencrypt-Docker.html