Table of Contents

Certbot

A software tool for auto-renewal of TLS certificates using Let's Encrypt.

Certbot offers DNS plugins: instead of a regular HTTP plugin that configure the local webserver and requests the ACME server make a HTTP request, the DNS plugin interfaces with the domain registrar to set a TXT record and requests the ACME server to make a DNS request.

This means certbot can provide two types of certificates:

  1. Domain/Subdomain-specific certificate
  2. Wildcard domain certificates

Domain-specific certificates

Easiest to use the nginx extension, when deploying on nginx web server. Simply add the configuration like so:

/etc/nginx/sites-enabled/notes.pyuxiang.com
server {
    server_name notes.pyuxiang.com;
    listen 80;
    ...

then run certbot, which will perform domain name auto-discovery:

sudo certbot

Certificates can be renewed with sudo certbot renew and deleted with sudo certbot delete. Logs for certbot is located in /var/log/letsencrypt. Example cron script:

# Let's Encrypt certificate auto-renewal (/var/log/letsencrypt)
0 0 * * 1 certbot renew

Enforce HTTPS

Other than using HSTS headers, server-side HTTPS can also be enforced in nginx using a redirect. This is automatically created by Certbot:

server {
    if ($host = pyuxiang.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
 
    listen 80;
    server_name pyuxiang.com;
    return 404; # managed by Certbot
}

Wildcard certificates

GoDaddy

Here's an example for GoDaddy, with credentials (key + secret)1) obtained from their developer portal. These credentials are ridiculously critical, so make sure they are given 0o660 permissions for root only.

Instructions below are for Ubuntu 22.04 LTS. Note that all these must be performed under the system python, due to permissions of secrets and write directories.

Install the pip package if not already installed, as well as the required certbot package and its extensions (for nginx and godaddy):

sudo apt install python3-pip
sudo pip3 install -U certbot certbot-nginx certbot-dns-godaddy

Renew certificate for both root and wildcard domains (note that the credentials here are located at /etc/nginx/godaddy_credentials.ini):

sudo certbot \
      --installer nginx --authenticator dns-godaddy \
      --dns-godaddy-credentials /etc/nginx/godaddy_credentials.ini \
      --dns-godaddy-propagation-seconds 900 \
      --keep-until-expiring --non-interactive --expand \
      --server https://acme-v02.api.letsencrypt.org/directory \
      --agree-tos --email pehyuxiang@gmail.com \
      -d 'pyuxiang.com' -d '*.pyuxiang.com'

The --dns-godaddy-propagation-seconds option sets the duration to wait for DNS changes to propagate after requesting for the certificate. Once certbot terminates, confirm the certificate with:

sudo openssl x509 -in /etc/letsencrypt/live/pyuxiang.com/fullchain.pem -text

If the certificate is not automatically installed, e.g. server name was not provided in any of the server blocks, then run after doing so:

sudo certbot install --cert-name pyuxiang.com

Other registrars

For domain registrars with stringent API access requirements (or which do not support API access in the first place), a more involved setup can include setting up your own ACME-DNS server to serve the DNS challenges instead. This will involve adding a _acme-challenge CNAME record to point to the server.

Otherwise, you can also setup using the manual TXT process with: sudo certbot certonly --manual --preferred-challenges dns -d "*.DOMAIN" -d "DOMAIN"

Deployment of wildcard certificates

Wildcard certificates can inevitably end up securing unintended subdomains. Avoid this by forcing a redirect to the root/redirection domain.

/etc/nginx/sites-enabled/_https_redirect
# Placeholder to redirect all invalid transactions
# directed at IP address, to snakeoil destination
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    include /etc/nginx/snippets/snakeoil.conf;
    return 404;
}
 
# Redirect all *.pyuxiang.com to root domain,
# unless overridden by more specific subdomain
server {
    listen 80;
    listen 443 ssl; # managed by Certbot
    server_name *.pyuxiang.com;
    ssl_certificate /etc/letsencrypt/live/pyuxiang.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/pyuxiang.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    return 301 https://pyuxiang.com;
}
Makefile
renew:
        sudo certbot \
                --installer nginx --authenticator dns-godaddy \
                --dns-godaddy-credentials /etc/nginx/dns01_credentials.ini \
                --dns-godaddy-propagation-seconds 120   \
                --keep-until-expiring --non-interactive --expand \
                --server https://acme-v02.api.letsencrypt.org/directory \
                --agree-tos --email pehyuxiang@gmail.com \
                -d 'pyuxiang.com' -d '*.pyuxiang.com'
 
manual:
        @echo "Do not explicitly change any certificates after deploying,"
        @echo "i.e. select 'c' when asked."
        sudo certbot run \
                --manual --preferred-challenges dns \
                --installer nginx \
                --keep-until-expiring --expand \
                --agree-tos --email pehyuxiang@gmail.com \
                -d 'pyuxiang.com' -d '*.pyuxiang.com'

Migrating away from Certbot now, due to the need for sudo.

1)
Format:
dns_godaddy_key = abcdefg
dns_godaddy_secret = hijk