When an automated Certbot renewal that previously worked suddenly starts failing, the cause almost always falls into one of a small number of categories — working through them systematically is far faster than guessing.
Step 1: read the actual error, not just "it failed"
sudo certbot renew --dry-run -v
Running with --dry-run and verbose output against Let's Encrypt's staging environment reproduces the failure without affecting your production certificate or hitting rate limits, and shows the specific error Certbot encountered — the actual message here should immediately point toward one of the categories below.
Category 1: challenge validation failure
If the error mentions the domain validation challenge failing (an HTTP-01 or DNS-01 challenge), something about how your server or DNS answers that specific challenge has changed since the last successful renewal — a firewall change blocking port 80, a webroot path that moved, a reverse proxy now intercepting the challenge path before it reaches Certbot's webroot, or (for DNS-01/wildcard certificates) an expired or revoked DNS API credential.
Category 2: rate limiting
If repeated failed renewal attempts have been occurring (perhaps silently, if nobody noticed the first failure), you may hit Let's Encrypt's rate limits, which will show as a specific rate-limit error message rather than a validation failure. The fix here is addressing the underlying cause of the repeated failures first — the rate limit itself will reset given some time, but retrying blindly without fixing the root cause just consumes more of your limited retry attempts.
Category 3: the renewal succeeded but the deploy hook failed
Occasionally the certificate itself renews successfully, but the deploy hook responsible for reloading your web server fails silently or errors out — meaning the new certificate exists on disk but your web server is still serving the old one until manually reloaded. Check your deploy hook command runs correctly when invoked manually, and check Certbot's logs specifically for hook execution errors, not just the certificate issuance portion.
Category 4: infrastructure changes Certbot doesn't know about
If your infrastructure has changed since the certificate was first issued — moved to a new server, added a CDN or reverse proxy in front, changed DNS providers — Certbot's stored configuration (in /etc/letsencrypt/renewal/) may reference a webroot path, plugin, or method that no longer matches your actual current setup. Reviewing this configuration file directly, rather than assuming it's still accurate, is worth doing after any significant infrastructure change.
Checking logs directly for the full picture
sudo cat /var/log/letsencrypt/letsencrypt.log
Certbot's own log file typically has more detail than what's shown in the terminal output, including the exact HTTP responses or DNS lookups involved in a failed challenge — worth checking directly rather than relying solely on the summarized terminal output.
What Certbot's verbose logging flag reveals beyond the default error summary
Running a renewal attempt manually with the -v or -vv flag shows Certbot's full internal process step by step, considerably more detail than the summary a scheduled cron job's default logging captures, often immediately revealing the specific validation step that's actually failing.
How to distinguish a rate-limit failure from a genuine validation failure
Certbot's error output for a rate-limit failure explicitly mentions rate limiting and typically references Let's Encrypt's rate limit documentation directly, distinctly different wording from a validation failure's more specific complaint about a failed challenge — reading the exact error message clarifies which category you're actually facing.
Why checking Let's Encrypt's own status page rules out a service-side issue
Before spending time troubleshooting your own configuration, a quick check of Let's Encrypt's public status page rules out the possibility that a renewal failure is actually caused by a temporary service-side outage or degradation on Let's Encrypt's own infrastructure, rather than anything wrong with your setup.
What a dry-run specifically tests versus a live renewal attempt
Certbot's --dry-run flag tests the entire validation and issuance process against Let's Encrypt's staging environment, exercising the same logic a real renewal would without actually consuming your production rate limit or replacing your live certificate — the ideal way to troubleshoot without any risk to your currently working setup.
How firewall changes can silently break a previously working renewal setup
A firewall rule change made for an unrelated reason can inadvertently block the specific port or path Certbot's validation depends on, causing a previously reliable renewal setup to start failing with no other configuration having changed — worth specifically checking firewall rules if a renewal that worked for months suddenly starts failing.
Why keeping Certbot itself updated matters for avoiding certain classes of failure
Certbot updates periodically include fixes for edge cases in specific web server or DNS plugin integrations, along with adapting to any changes in the ACME protocol or CA requirements — running a meaningfully outdated Certbot version increases the chance of hitting an already-fixed bug that a current version wouldn't encounter.
What Certbot's plugin-specific error messages reveal that generic errors don't
A failure specific to your configured plugin (the Nginx plugin failing to modify configuration, for instance) produces a distinctly different error than a validation failure — reading which specific stage of the process failed, plugin configuration versus domain validation versus certificate installation, narrows down where to actually look.
How webroot-based validation failures differ in cause from standalone-mode failures
Webroot-based validation fails most commonly due to file permission issues or an incorrectly configured webroot path, while standalone mode (which temporarily runs its own server) fails most commonly due to port 80 already being in use by another process — these represent genuinely different failure categories requiring different specific fixes.
Why testing renewal immediately after any server configuration change catches a regression early
Proactively testing a dry-run renewal immediately after any unrelated server configuration change, a firewall rule update, a web server config change, catches a renewal-breaking regression immediately after the change that caused it, while the specific change is still fresh in memory, rather than discovering the break weeks later when an actual renewal fails.
A quick checklist for resolving most renewal failures
Run with -v for detailed output, confirm the validation method's specific requirement (port 80 reachable, or DNS API credentials current), check for a firewall or configuration change made since the last successful renewal, and confirm you're not hitting a rate limit — four checks resolving the large majority of renewal failures.
Why treating renewal failures as urgent, not routine, protects against real outages
A failed renewal attempt today still leaves time before the certificate actually expires, but treating each failure as worth immediate investigation, rather than assuming the next scheduled attempt will simply succeed on its own, is what actually prevents a failure from silently recurring until the certificate genuinely expires.