How to obtain an SSL certificate for a containerised web application - for free! - The SSL

SSL Certification

Okay, so we're ready to generate an SSL certificate for our web application. There are a few prerequisites for this:

  1. A fully registered domain name, i.e.
  2. A DNS A record with pointing to your VPS's public IP address.
  3. A DNS A record with pointing to your VPS's public IP address.

So, firstly, we need to install a tool called Certbot. To do this, you need to SSH into your VPS and run the following commands:

sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install certbot

Certbot has to answer a cryptographic challenge provided by the Let's Encrypt API. It uses port 80 or 443 to accomplish this, so you need to allow this port in your firewall. If you're on a Digital Ocean Ubuntu 18.0.4 machine, then you need these commands:

sudo ufw allow 80
sudo ufw allow 443

Be sure now to kill any processes that are currently using these ports. For example, if you have your web application running. If you do not then Certbot will fail to bind to the appropriate port and the request for certification will fail. To generate a certificate we are going to use Certbot's standalone mode:

sudo certbot certonly --standalone --preferred-challenges http -d

After being prompted to enter your email address and accept terms and conditions you should receive a message similar to the following:

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   Your cert will expire on 2019-03-19. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew all* of your certificates, run
   "certbot renew"

You'll notice that the directories where the private key and certificate file have been stored are the same as the ones that we have already specified in our configuration files. Each certificate is valid for 90 days. Renewal can be handled automatically using cron. To start, open the cron file using crontab -e. In the cron file we can add a new line, replacing the filepaths with the filepath of your docker-compose.yml:

@weekly certbot renew --pre-hook "docker-compose -f path/to/docker-compose.yml down" --post-hook "docker-compose -f path/to/docker-compose.yml up -d"

After saving the cron file we now have a renewal check scheduled weekly. To do this check, we need access to ports 80 and 443; this means that we need to kill our application before the check and start it after the check. This is handled by the --pre-hook and -–post-hook arguments. If Certbot detects that an SSL certificate will expire within 30 days then it will be renewed.

Lastly, you can check to see if the renewal command will work correctly by using the following command:

sudo certbot renew –dry-run

Feel free to add the --pre-hook and -–post-hook arguments to the dry run of the renewal, however only do this if you already have your application on your VPS, otherwise you'll attempt to reference files that do not yet exist.