Skip to main content

Certbot

Source

Using Free SSL/TLS Certificates from Let’s Encrypt with NGINX


Overview

This guide covers how to obtain, renew, and manage SSL/TLS certificates from Let’s Encrypt using Certbot’s NGINX plugin and the DNS‑01 challenge via Cloudflare. It also explains how to remove domains from existing certificates and automate certificate updates with a cron-driven script.


Prerequisites

  • A server running NGINX.
  • Certbot installed (sudo certbot python3-certbot-nginx python3-certbot-dns-cloudflare).
  • A Cloudflare account with an API token or global API key.
  • SSH access (with key) for any remote certificate distribution.

Obtain Certificates via NGINX Plugin

Use Certbot’s NGINX plugin to automatically obtain a certificate and configure NGINX in one step:

sudo certbot --nginx -d x.abair.ie

This command will:

  1. Obtain a certificate from Let’s Encrypt.
  2. Modify your NGINX configuration to use the new certs.
  3. Reload NGINX to apply the changes.

Remove a Domain from an Existing Certificate

To remove an unwanted domain from a multi-domain certificate:

  1. Open the renewal config:
    sudo nano /etc/letsencrypt/renewal/yourdomain.conf
  2. In the domains line, delete the -d unwanted.domain.tld entry.
  3. Re-run Certbot for the remaining domains:
    sudo certbot certonly --nginx --cert-name yourdomain -d remaining.domain.tld

For a detailed walkthrough, see Remove domain from certbot and NGINX.


DNS Cloudflare Function

Certbot’s Cloudflare DNS plugin automates DNS‑01 challenges by programmatically creating and cleaning up TXT records in Cloudflare:

  1. Install the plugin:
    sudo apt install python3-certbot-dns-cloudflare
  2. Create credentials file (/root/certbot-creds.ini):
    # Using a Global API Key
    dns_cloudflare_email = your-email@example.com
    dns_cloudflare_api_key = 0123456789abcdef...

    # Or, using a Scoped API Token
    dns_cloudflare_api_token = 0123456789abcdef...
  3. Secure the file:
    chmod 600 /root/certbot-creds.ini
  4. Obtain or renew certificates:
    sudo certbot certonly \
    --dns-cloudflare \
    --dns-cloudflare-credentials /root/certbot-creds.ini \
    -d '*.abair.ie' -d abair.ie

This process:

  • Verifies domain control via Cloudflare DNS.
  • Automatically removes challenge records after issuance.

update-ssl-certs Script

Automate certificate renewal and distribution with a Bash script (update-ssl-certs.sh):

#!/bin/bash
# Paths and credentials
CERT_PATH="/etc/letsencrypt/live/abair.ie/"
CREDS="/root/certbot-creds.ini"
SSH_KEY="/root/.ssh/id_ed25519"

# Domains to renew
domains=(
"*.abair.ie"
"abair.ie"
"*.scealai.abair.ie"
"*.geabaire.abair.ie"
)

# Renew via Cloudflare DNS challenge
for d in "${domains[@]}"; do
certbot certonly \
--dns-cloudflare \
--force-renew \
--dns-cloudflare-credentials "$CREDS" \
-d "$d"
done

# Remote VM details
REMOTE_USER="services"
REMOTE_HOST="10.0.0.2"
REMOTE_PORT="22102"

# Copy certificates to services VM
scp -i "$SSH_KEY" -P "$REMOTE_PORT" \
"$CERT_PATH/fullchain.pem" "$REMOTE_USER"@$REMOTE_HOST:/etc/ssl/abair.ie
scp -i "$SSH_KEY" -P "$REMOTE_PORT" \
"$CERT_PATH/privkey.pem" "$REMOTE_USER"@$REMOTE_HOST:/etc/ssl/abair.ie

# Restart remote Docker registry to load new certs
ssh -i "$SSH_KEY" -p "$REMOTE_PORT" $REMOTE_USER@$REMOTE_HOST \
"docker compose -f /home/services/docker-registry/docker-compose.yml restart"

Scheduling: Add to root’s crontab to run every 60 days at midnight:

0 0 */60 * * /usr/local/bin/update-ssl-certs.sh >> /var/log/update-ssl-certs.log 2>&1