Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Using Certbot Docker Image

Prerequisites

This tutorial assumes you have installed Docker.

Table Of Contents

Single Domain - Web Challenge

This will show you how to use the Certbot Docker image to generate Lets Encrypt SSL certificates through a web based challenge whereby this serves up a webpage with a token LetsEncrypt will look for on your domain. If it is able to find the token, it proves that you have control of the domain and thus can be provided with SSL certificates for that domain.

Thus, this method requires that this action be taken on the server that the domain points to, and also requires ports 80 and 443 whilst it runs, so your website will likely be unavailable whilst this runs.

Run the command below on your server (after changing the DOMAIN variable)

DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
LETSENCRYPT_VOLUME_DIR=$DIR/letsencrypt
DOMAIN="www.mydomain.com"
EMAIL="my-email@gmail.com"

sudo docker run \
  --rm \
  --name certbot \
  -p 80:80 \
  -p 443:443 \
  -v "$LETSENCRYPT_VOLUME_DIR:/etc/letsencrypt" \
  certbot/certbot \
  certonly \
  -d $DOMAIN \
  --standalone \
  --email=$EMAIL \
  --agree-tos \
  --no-eff-email

# Copy the certificate files  to local folder and set permissions
sudo cp --recursive --dereference $DIR/letsencrypt/live/$DOMAIN .
sudo chown $USER:$USER --recursive $DOMAIN

Certbot creates the certificate files in $LETSENCRYPT_VOLUME_DIR/archive with a symlink to the latest ones in $LETSENCRYPT_VOLUME_DIR/live, so that's why we can copy them using --dereference.

Wildcard Certificate - DigitalOcean DNS Challenge

If one uses a DNS provider, that has a supported Certbot DNS plugin, then you can easily generate wildcard certificates for your domain using the relevant plugin image. You can find the list of Certbot DNS Plugins on the Certbot Dockerhub page.

In this case, I am using DigitalOcean to manage my DNS records, and thus will be using the certbot/dns-digitalocean image. If you are using a different provider, swap out the image name, and update the credentials as required.

The following script will create a wildcard certificate for your domain, and place it in a folder named after your domain, on the same level of the script's location.

#!/bin/bash

# Specify your domain here (make sure there is no subdomain/wildcard)
DOMAIN="mydomain.com"

# Specify your email address for Lets encrypt to send you expiry reminders on
EMAIL="me@mydomain.com"

# Put your DigitalOcean token here.
DO_TOKEN="58xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx9"

# Get the path to the directory ths script is in.
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )

# Specify where to store the Lets Encrypt volume, where all of Certbot's state will be kept.
LETSENCRYPT_VOLUME_DIR=$DIR/letsencrypt

# Create our DigitalOcean credentials file for Certbot to use.
echo "dns_digitalocean_token = ${DO_TOKEN}" > $DIR/certbot-creds.ini
chmod 600 $DIR/certbot-creds.ini

sudo docker run \
  --rm \
  --name certbot \
  -v "$DIR/certbot-creds.ini:/certbot-creds.ini:ro" \
  -v "$LETSENCRYPT_VOLUME_DIR:/etc/letsencrypt" \
  certbot/dns-digitalocean \
  certonly \
  --dns-digitalocean \
  --email=$EMAIL \
  --agree-tos \
  --no-eff-email \
  --keep-until-expiring \
  --dns-digitalocean-credentials /certbot-creds.ini \
  -d "*.${DOMAIN}"

sudo cp --recursive --dereference $DIR/letsencrypt/live/$DOMAIN .
sudo chown $USER:$USER --recursive $DOMAIN

# cleanup
rm $DIR/certbot-creds.ini
  • ---dns-digitalocean tells certbot we want a DNS based challenge using DigitalOcean
  • --agree-tos - tells certbot that we agree to the terms of service.
  • --no-eff-email - tells certbot we do not want to be used for statistics.
  • --keep-until-expiring - tells certbot to do nothing if we were to run again before the certificate is even close to expiring.
  • --dns-digitalocean-credentials specifies the path to our credentials file (which needs to line up with the volume declaration).

The full list of command line options for Certbot can be viewed online

Multi-Domain Certificate - Cloudflare DNS Challenge

The following example will show you how you can use certbot to provision an SSL certificate that covers www.mydomain.com and mydomain.com, which is a common case.

#!/bin/bash

#specify your domain (e.g. without the www subdomain)
DOMAIN="mydomain.org"

# Specify your email address for Lets encrypt to send you expiry reminders on
EMAIL="my.email@gmail.com"

# Put your cloudflare token here (needs zone edit permissions to the relevant domain)
CLOUDFLARE_TOKEN="putYourCloudflareTokenHere"

# Get the path to the directory ths script is in.
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )

# Specify where to store the Lets Encrypt volume, where all of Certbot's state will be kept.
LETSENCRYPT_VOLUME_DIR=$DIR/letsencrypt

# Create our DigitalOcean credentials file for Certbot to use.
echo "dns_cloudflare_api_token = ${CLOUDFLARE_TOKEN}" > $DIR/certbot-creds.ini
chmod 600 $DIR/certbot-creds.ini

sudo docker run \
  --rm \
  --name certbot \
  -v "$DIR/certbot-creds.ini:/certbot-creds.ini:ro" \
  -v "$LETSENCRYPT_VOLUME_DIR:/etc/letsencrypt" \
  certbot/dns-cloudflare \
  certonly \
  --dns-cloudflare \
  --email=$EMAIL \
  --agree-tos \
  --no-eff-email \
  --keep-until-expiring \
  --dns-cloudflare-propagation-seconds 30 \
  --dns-cloudflare-credentials /certbot-creds.ini \
  -d "${DOMAIN},www.${DOMAIN}"

sudo cp --recursive --dereference $DIR/letsencrypt/live/$DOMAIN .
sudo chown $USER:$USER --recursive $DOMAIN

# cleanup
rm $DIR/certbot-creds.ini

You may not need --dns-cloudflare-propagation-seconds 30 but I find that I quite often do.

References

Last updated: 27th June 2024
First published: 12th March 2021

This blog is created by Stuart Page

I'm a freelance web developer and technology consultant based in Surrey, UK, with over 10 years experience in web development, DevOps, Linux Administration, and IT solutions.

Need support with your infrastructure or web services?

Get in touch