Certbot renewal hooks run local scripts when a certificate renewal reaches a defined phase. Configure one when a renewed certificate must trigger a service reload, file sync, or deployment step so the new certificate is actually used after Certbot updates the live certificate files.
Directory hooks are the simplest durable place for host-wide renewal behavior. Certbot checks the hook directories under its configuration directory, runs executable files in byte-sorted filename order, and keeps command-line or saved renewal hooks separate from those directory files.
A deploy hook fits service reloads because it runs only after a successful renewal. Use a pre and post pair only when Certbot must temporarily stop a service before validation and start it again after the attempt.
Related: Test Certbot certificate renewal
Related: Check the Certbot renewal timer
Related: Configure a Certbot deploy hook
Steps to configure a Certbot renewal hook:
- Choose the hook phase before creating the script.
Hook directory When it runs Use it for /etc/letsencrypt/renewal-hooks/pre Before a renewal attempt that will actually run Temporarily stopping a service that conflicts with validation, such as a standalone listener on port 80. /etc/letsencrypt/renewal-hooks/deploy After a successful renewal Reloading a web server, syncing renewed certificate files, or notifying a dependent service. /etc/letsencrypt/renewal-hooks/post After a renewal attempt finishes Starting a service that was stopped by a matching pre hook, even if renewal failed. For service reloads, prefer a deploy hook. A plain certbot renew exit status can be 0 when no certificate needed renewal, so it is not enough proof that a certificate changed.
- Create the deploy hook directory if it is missing.
$ sudo install -d -m 755 /etc/letsencrypt/renewal-hooks/deploy
- Create the hook script.
$ sudoedit /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/sh set -eu systemctl reload nginx
Replace systemctl reload nginx with the service command that must run after a renewed certificate is available. Keep the hook non-interactive because automatic renewal may run from systemd or cron with no terminal.
A hook that exits with an error is printed in Certbot output, but Certbot still attempts the renewal. Test destructive or restart-heavy commands by hand before leaving them in a renewal hook.
- Make the hook executable.
$ sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
- Confirm the executable hook is in Certbot's deploy hook directory.
$ sudo find /etc/letsencrypt/renewal-hooks/deploy -maxdepth 1 -type f -perm -111 -print /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
If more than one hook must run in a specific order, prefix filenames with sortable numbers such as 10-reload-nginx.sh and 20-sync-certs.sh.
- Run the command inside the hook once before relying on renewal automation.
$ sudo systemctl reload nginx
For Nginx, run sudo nginx -t before reloading if the hook reloads a service after configuration changes. For another service, use that service's own syntax or health check before placing the command in the hook.
- Run a renewal dry run and include deploy hooks in the test.
$ sudo certbot renew --dry-run --run-deploy-hooks Saving debug log to /var/log/letsencrypt/letsencrypt.log Processing /etc/letsencrypt/renewal/example.com.conf Simulating renewal of an existing certificate for example.com Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/example.com/fullchain.pem (success)
During --dry-run, Certbot runs pre and post hooks by default. Deploy hooks run during a dry run only when --run-deploy-hooks is included, and they use the currently active certificate files rather than the temporary staging certificate.
If the output says No simulated renewals were attempted., the host does not have a renewal configuration that Certbot can test. Run the dry run on the server that already owns the certificate lineage.
- Let the normal renewal schedule call the hook after the dry run succeeds.
$ sudo certbot renew Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No renewals were attempted. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
A normal renewal check may do nothing when certificates are not near expiry. The hook runs when Certbot actually obtains or renews a certificate in the matching phase.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.