HTTPS in a Dockerized frontend + auto-renewal (NGINX and Let’s Encrypt)

aminbe
3 min readApr 20, 2021

Instantiation of the environment

If you ever want to reproduce this exercise, this tutorial cost me 0$

Virtual machine

In order to obtain a free public IP address, we subscribed to a free trial offer of Google Cloud Platform.

For information, the 3 major cloud services providers (aws, azure and gcp) provide free tier offers.

We can create a VM instance following this link.

We write a simple “Hello World” web site.

We set up an NGINX container that serves the “hello world” static web page :

$ sudo docker run --name nginx-static-website -v ~/html/hello-world:/usr/share/nginx/ht
ml -p 80:80 -d nginx

Our static page is accessible through internet !

Domaine name

We can register a domain name for free at freenom.com.

In our case, we register aminebenaddi.tk :

We should then forward the domain name to the public IP address :

It may take up to 72 hours for the redirection to be activated. In my case, I had to wait 24 hours.

Intermediate result 🎉

Generation of let’s encrypt certificates

This part is largely inspired by this link and this repository.

We define a shared volume so that our static files are served by nginx container. Also, as recommended, an attempt to renew certificates is made every 12 hours. Certificates are not effectively renewed until the expiry date approaches.

Also shared volumes are defined between the certbot container and the nginx container. This is to make the certificates provided by certbot available to the web server.

Our docker-compose will look like :

version: '3'

services:
nginx:
image: nginx:latest
restart: unless-stopped
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
- ./hello-world:/usr/share/nginx/html
ports:
- "80:80"
- "443:443"
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \\"daemon off;\\"'"
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

Also, our nginx configuration should allow us to :

  • Serve certbot file for acme challenge
  • Mention where public and private keys are located
  • Include recommended let’s encrypt configuration
server {
listen 80;
server_name aminebenaddi.tk;
server_tokens off; location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name aminebenaddi.tk;
server_tokens off; root /usr/share/nginx/html;

ssl_certificate /etc/letsencrypt/live/aminebenaddi.tk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/aminebenaddi.tk/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

location / {
try_files $uri /index.html;
}
}

Finally, since dummy certificates are needed in order to realize the first acme challenge, authors of the repo provide a bash script.

The remaining steps are :

  • Executing the [init-letsencrypt.sh] bash file
  • Run the server sudo docker-compose up -d

End result 🥳

HTTPS is activated :

Extra-link

An implementation : https://github.com/AmineBenaddiGitHub/nginx-certbot

--

--