9 min read

Why Your SSL Certificate Keeps Expiring (And How to Fix It)

By Jason Gilmore
SSL certificate expired SSL renewal failed certificate expiration auto-renewal not working Let's Encrypt renewal SSL troubleshooting
If your SSL certificate keeps expiring unexpectedly, the problem is usually with your renewal automation, not your certificate provider. Learn the common causes and how to fix them for good.

TL;DR: SSL certificates that keep expiring are almost always caused by broken auto-renewal systems, not faulty certificates. The most common culprits are changed file permissions, web server configuration updates that break HTTP validation, DNS changes that prevent domain verification, and renewal scripts that fail silently without notification. The fix involves monitoring your renewal process independently from the renewal itself.

You set up Let's Encrypt with auto-renewal, verified it was working, and moved on to other things. Then three months later you're scrambling because visitors are seeing security warnings. Sound familiar? You're not alone. This is one of the most common problems indie hackers and small teams face with SSL certificates.

What Causes Repeated SSL Expiration?

When an SSL certificate expires repeatedly despite having auto-renewal configured, the certificate itself is rarely the problem. Auto-renewal systems fail for predictable reasons: server configuration changes break the renewal process, permissions drift over time, or the renewal script encounters errors but has no way to alert you. The certificate provider is doing its job. The breakdown happens between your server and the renewal client.

Why This Keeps Happening to Indie Hackers

Running a SaaS or web application as a solo founder means you're constantly context-switching. You can't babysit every automated process, and SSL renewal is exactly the kind of "set it and forget it" task that causes problems when you forget it.

The cruel irony is that auto-renewal works perfectly for months or even years, then fails at the worst possible time. A server migration, a security update, or even a routine package upgrade can break the renewal process without any obvious indication.

This matters more than you might think. Modern browsers don't just warn users about expired certificates. They actively block access with scary full-screen warnings. Your conversion rate drops to nearly zero while the certificate is expired, and some users who encountered the warning may never return.

Common Causes of SSL Renewal Failure

Certbot or ACME Client Failures

The renewal client itself can stop working for several reasons.

Package updates sometimes change Certbot's behavior or configuration file locations. After a major system update, your renewal hooks might point to files that no longer exist or have moved.

Memory limitations on small VPS instances can cause Certbot to fail silently during renewal. If your server is running tight on RAM, the renewal process might get killed by the OOM killer before completion.

Python environment issues affect Certbot specifically because it's a Python application. Virtual environment changes, Python version updates, or dependency conflicts can break renewals.

HTTP Validation Problems

Let's Encrypt's most common validation method requires placing a file in your web root and having Let's Encrypt fetch it over HTTP port 80.

If you've configured your web server to redirect all HTTP traffic to HTTPS (which you should for production), you need to ensure the redirect has an exception for the ACME challenge path. Without this exception, Let's Encrypt can't validate your domain.

Firewall changes that block port 80 will break HTTP validation entirely. Some hardening scripts close port 80 assuming all traffic should be HTTPS, not realizing that certificate renewal needs HTTP access.

CDN or proxy configurations like Cloudflare can intercept the validation request and prevent Let's Encrypt from seeing your challenge file. If you've enabled Cloudflare's "Always Use HTTPS" setting, you'll need to create a page rule exception for the challenge path.

DNS Validation Issues

If you use DNS validation instead of HTTP validation, different problems can occur.

API credential expiration is common with DNS providers that use API tokens with limited lifetimes. Your renewal worked fine until the token expired, and now every renewal attempt fails.

DNS propagation delays can cause validation timeouts. If your DNS provider is slow to propagate changes, Let's Encrypt might check for the validation record before it's visible.

Changed DNS hosting means you need to update your ACME client configuration. If you moved from Route53 to Cloudflare but didn't update your Certbot DNS plugin configuration, renewals will fail.

Permission and Ownership Changes

Certbot needs specific permissions to read configuration files and write new certificates.

Running Certbot as a different user than originally configured will cause permission errors. This often happens after server migrations or when changing deployment processes.

SELinux or AppArmor restrictions on newer distributions can block Certbot from accessing certain paths. Security policy updates might add restrictions that weren't present during initial setup.

Web server configuration file permissions sometimes prevent Certbot from reloading the configuration after renewal. The certificate might renew successfully, but the new certificate never gets loaded.

How to Fix SSL Renewal for Good

Step 1: Test Your Current Renewal Setup

Before making changes, understand what's currently broken. Run a dry-run renewal to see what errors occur:

sudo certbot renew --dry-run

Check the Certbot logs for detailed error messages:

sudo cat /var/log/letsencrypt/letsencrypt.log

Verify your current certificate's expiration date:

echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates

Step 2: Fix the Underlying Issue

Based on what you find, address the specific problem.

For HTTP validation issues, ensure the ACME challenge path isn't being redirected. In Nginx, add a location block before your HTTPS redirect:

location ^~ /.well-known/acme-challenge/ {
    allow all;
    root /var/www/html;
}

For permission issues, verify Certbot can access its directories:

sudo ls -la /etc/letsencrypt/
sudo ls -la /var/log/letsencrypt/

For DNS validation, verify your API credentials are still valid and update them if necessary.

Step 3: Add Independent Monitoring

This is the step most people skip, and it's the most important. Your renewal process and your monitoring should be completely separate systems.

If your renewal fails and your only alert system is part of the same server, you might not find out until users report problems. External monitoring catches failures that internal scripts miss.

SSL monitoring tools check your certificate from outside your infrastructure and alert you when expiration is approaching, regardless of whether your renewal automation is working.

Step 4: Set Up Multiple Alert Thresholds

Don't rely on a single "your certificate is about to expire" warning. Configure alerts at multiple intervals:

90 days out serves as a first warning that's especially useful if you're using commercial certificates with longer validity periods.

30 days out means something is probably wrong if auto-renewal hasn't triggered yet for Let's Encrypt certificates.

7 days out requires immediate investigation. Manual intervention is likely needed.

1 day out is an emergency requiring immediate action.

Step 5: Document Your Recovery Process

Write down exactly how to manually renew your certificate when automation fails. Include the specific commands for your setup, the location of your certificates and configuration files, who has access to the server, and any DNS credentials or API tokens needed.

When an SSL emergency happens, you don't want to be figuring this out under pressure.

Preventing Future Expiration Issues

Schedule regular renewal tests, not just dry runs, but actual verification that the full process works. Monthly tests catch problems before they become emergencies.

Keep your ACME client updated. Certbot releases include bug fixes and compatibility updates for changes at Let's Encrypt.

Monitor your server's scheduled tasks. Verify that the cron job or systemd timer for renewal is still in place and hasn't been accidentally removed:

sudo systemctl list-timers | grep certbot

If you use DNS validation, set calendar reminders for API credential renewals. Many DNS providers issue tokens with 90-day or one-year lifetimes.

Common Mistakes to Avoid

Assuming "it worked once so it'll keep working" is how most SSL emergencies start. Automation requires ongoing verification.

Testing only with dry-run misses some failure modes. Dry-run tests skip certain steps that might fail during actual renewal, like web server reload hooks.

Having renewal alerts go to an unmonitored channel defeats the purpose of monitoring. Make sure SSL alerts reach someone who will act on them, even on weekends.

Ignoring the first warning because you assume auto-renewal will handle it is risky. If you get a 30-day warning and you're using Let's Encrypt, something is probably wrong with your automation.

Running renewal manually and forgetting to fix the underlying automation issue just delays the problem until next time.

How SecurityBot Helps

SecurityBot's SSL monitoring provides an independent check on your SSL certificates that works regardless of your renewal method. You get alerts at 90, 30, 7, and 1 day before expiration, giving you multiple opportunities to catch problems before they affect users.

Because SecurityBot checks from outside your infrastructure, it catches problems that internal monitoring might miss, like certificates that renewed successfully but didn't get deployed, or CDN configurations that are serving an old certificate.

The monitoring runs continuously and doesn't depend on your server's cron jobs, scheduled tasks, or renewal automation being functional.

Start your free 14-day trial and monitor all your SSL certificates from one dashboard.

Frequently Asked Questions

Why does Let's Encrypt use 90-day certificates?

Shorter certificate lifetimes force automation and reduce the window of exposure if a certificate is compromised. While 90 days might seem inconvenient, it actually encourages better security practices than longer-lived certificates that get renewed manually.

Should I switch to a paid certificate to avoid this?

Paid certificates with longer validity periods (one to two years) have the same renewal problem, just less frequently. You'll still need monitoring and still need to ensure renewals don't fail. The extra cost doesn't eliminate the need for good certificate management.

What if my hosting provider manages SSL?

Managed SSL services from providers like Cloudflare, Netlify, or Vercel handle renewal automatically and rarely have problems. If you're using managed hosting, certificate expiration is much less likely but still worth monitoring as a sanity check.

How do I know if renewal failed silently?

The only reliable way is external monitoring. Check your certificate's current expiration date and compare it to when renewal should have run. If your certificate still shows the old expiration date after when auto-renewal should have triggered, your renewal is failing.

Can I renew a certificate that's already expired?

Yes, you can renew an expired certificate. The renewal process is the same. However, your site will show security warnings until the new certificate is in place, which is why prevention is better than cure.


Last updated: January 2026 | Written by Jason Gilmore, Founder of SecurityBot

Published on January 27, 2026 by Jason Gilmore
Share: