A renewal timer that has never actually renewed anything is a timer that will fail in sixty days, and the first sign will be a browser warning.
$ certbot renew --dry-run
Simulating renewal of an existing certificate for example.com
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
# and the hook that must also be tested
$ certbot renew --dry-run --deploy-hook 'systemctl reload nginx'
The dry run uses the staging environment, so it exercises the whole path — challenge, validation, hook — without touching the rate limit. The deploy hook is the half that fails silently in real life: the certificate renews, nginx keeps serving the old one from memory, and nothing is wrong until somebody notices the expiry date in a browser. Running the dry run monthly from cron and alerting on a non-zero exit is ten minutes of work.