Skip to main content

Certificate renewal

Manual renewal

Generate with certbot

sudo docker run -it --rm \
-v /etc/letsencrypt:/etc/letsencrypt \
-v /var/lib/letsencrypt:/var/lib/letsencrypt \
certbot/certbot certonly \
--manual --preferred-challenges dns \
-d people-t.com -d '*.people-t.com' \
--agree-tos -m dbeletsis@people-t.com

Certificate is saved at: /etc/letsencrypt/live/people-t.com/fullchain.pem

Key is saved at: /etc/letsencrypt/live/people-t.com/privkey.pem

Restart WordPress

Choose ONE of the options below.

  • The right way

    sudo docker exec wordpress-nginx nginx -t
    sudo docker exec wordpress-nginx nginx -s reload
  • The very manual way

    docker compose -f ~/wordpress-root/compose.yml --env-file ~/wordpress-root/.env.wordpress down
    docker compose -f ~/wordpress-root/compose.yml --env-file ~/wordpress-root/.env.wordpress up -d

    -f ~/wordpress-root/compose.yml --env-file ~/wordpress-root/.env.wordpress are required options.

Automatic renewal

Setup

  1. Create API token in Cloudflare.

    SettingValue
    PermissionsZone · DNS · Edit
    PermissionsZone · Zone · Read
    Zone ResourcesInclude · Specific zone · people-t.com

    Obviously, this requires the proper access to the DNS settings of people-t.com.

  2. Save it to the machine's environment.

    sudo mkdir -p /root/.secrets
    echo "dns_cloudflare_api_token = <TOKEN>" | sudo tee /root/.secrets/cloudflare.ini
    sudo chmod 600 /root/.secrets/cloudflare.ini

Test run

  1. Issue certificate with Cloudflare plugin.

    sudo docker run --rm \
    -v /etc/letsencrypt:/etc/letsencrypt \
    -v /var/lib/letsencrypt:/var/lib/letsencrypt \
    -v /root/.secrets:/secrets:ro \
    certbot/dns-cloudflare certonly \
    --dns-cloudflare \
    --dns-cloudflare-credentials /secrets/cloudflare.ini \
    --dns-cloudflare-propagation-seconds 30 \
    --cert-name people-t.com \
    -d people-t.com -d '*.people-t.com' \
    --agree-tos -m dbeletsis@people-t.com \
    --force-renewal \
    --non-interactive
  2. Confirm change.

    sudo grep -E 'authenticator|credentials' /etc/letsencrypt/renewal/people-t.com.conf

    Should print the following:

    authenticator = dns-cloudflare
    dns_cloudflare_credentials = /secrets/cloudflare.ini
  3. Prove renewal works (Dry-run).

    sudo docker run --rm \
    -v /etc/letsencrypt:/etc/letsencrypt \
    -v /var/lib/letsencrypt:/var/lib/letsencrypt \
    -v /root/.secrets:/secrets:ro \
    certbot/dns-cloudflare renew --dry-run

    This will take about 1 minute to execute.

    Expected result:

    Saving debug log to /var/log/letsencrypt/letsencrypt.log

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Processing /etc/letsencrypt/renewal/people-t.com.conf
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Account registered.
    Simulating renewal of an existing certificate for people-t.com and *.people-t.com
    Waiting 30 seconds for DNS changes to propagate

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Congratulations, all simulated renewals succeeded:
    /etc/letsencrypt/live/people-t.com/fullchain.pem (success)
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Actual run and Cron

We have pre-created a script in /usr/local/bin/renew-certs.sh.

  1. Give permissions to execute script.

    sudo chmod 700 /usr/local/bin/renew-certs.sh
  2. Run manually to test.

    sudo /usr/local/bin/renew-certs.sh

    Expect valid 89 more days and exit 0.

  3. Schedule it.

    sudo crontab -e
    MAILTO="dbeletsis@people-t.com,sdermanoutsos@people-t.com"
    17 3,15 * * * /usr/local/bin/renew-certs.sh >> /var/log/certbot-renew.log 2>&1
  4. Verify what's actually served.

    echo | openssl s_client -connect people-t.com:443 -servername people-t.com 2>/dev/null \
    | openssl x509 -noout -dates -subject -ext subjectAltName

    Expected output:

    notBefore=Jul 28 06:37:40 2026 GMT
    notAfter=Oct 26 06:37:39 2026 GMT
    subject=CN = people-t.com
    X509v3 Subject Alternative Name:
    DNS:*.people-t.com, DNS:people-t.com
  5. Confirm that cron job runs properly.

    sudo env -i PATH=/usr/bin:/bin HOME=/root /usr/local/bin/renew-certs.sh

    This also confirms it runs from its own environment instead of our shell.