Profile    Mohammed Shiroz Status   Loading  
Logo
Share This
Back to blog
Filter by:
Tags
//Article title

How HTTPS Certificates Renew Themselves: Let's Encrypt and ACME Explained

About Post

Somewhere on your server, a small program wakes up twice a day, checks a date, and almost always goes back to sleep. You've probably never looked at it. You set it up once, years ago maybe, by copying a command from a tutorial.

When it works, nobody thinks about it. When it quietly stops working, you find out weeks later, when every visitor to your site gets a full-page browser warning and your phone starts ringing.

Let's open the box: how a free certificate gets issued and renewed without a human, what can break, and the one check you should add today.

Why the certificates are so short-lived

A Let's Encrypt certificate is valid for 90 days. Traditional certificates used to last a year or more, so 90 days can feel like a hassle. It's deliberate.

  • Less damage from a leaked key. If a private key is stolen, a short-lived certificate stops being useful much sooner.
  • It forces automation. Nobody renews something by hand four times a year for long. Short lifetimes make the automated path the only sensible one, and automated renewal is far more reliable than a calendar reminder.

The whole industry is moving in this direction: the CA/Browser Forum, which sets the rules for publicly trusted certificates, has voted to shrink the maximum certificate lifetime in stages over the next few years. Manual renewal is on its way out everywhere, not just with Let's Encrypt.

ACME: the conversation behind the certificate

The automation runs on a protocol called ACME (Automatic Certificate Management Environment), standardised as RFC 8555. A client on your server, most often certbot, talks to the certificate authority. Simplified, the conversation goes like this:

  1. "Hi, I'm account X." The client has an account key pair, created the first time you ran it. Every request is signed with it.
  2. "I'd like a certificate for example.com." The client places an order.
  3. "Prove you control example.com." The CA hands back one or more challenges.
  4. "Done, go check." The client completes a challenge and the CA verifies it from the outside.
  5. "Here's my CSR." The client generates a key for the certificate and sends a certificate signing request.
  6. "Here's your certificate." The client downloads it, along with the intermediate chain.

Notice what's missing: no human, no email, no payment, no document. Control of the domain is the only thing being proven, and it's proven fresh each time.

The challenges: how you prove you own the domain

ChallengeHow you prove controlGood forWatch out for
HTTP-01Serve a token at http://your-domain/.well-known/acme-challenge/<token>A normal web server with port 80 openNo wildcards; port 80 must be reachable
DNS-01Create a TXT record at _acme-challenge.your-domainWildcard certificates, servers not reachable from the internetNeeds API access to your DNS provider, and a token to protect
TLS-ALPN-01Answer a special TLS handshake on port 443Setups where only 443 is openLess common; fewer clients and servers support it

Most Laravel apps on a VPS use HTTP-01 through the web server plugin, which is why "certbot --nginx" feels like magic: it temporarily answers the challenge for you and then edits your server config to use the new certificate.

What renewal actually does

When you install certbot from a package or snap, it also installs a scheduled task: a systemd timer or a cron entry that runs certbot renew about twice a day. Most runs do nothing. A certificate is only renewed when it's getting close to expiry; the usual guidance is to renew with about a third of the lifetime left, so around 30 days for a 90-day certificate.

That gives you a generous buffer. If a renewal fails, the next run tries again, and there are weeks of retries before anything visible breaks. Which is precisely why failures go unnoticed.

Three commands worth knowing:

# Is the timer actually there and scheduled?
systemctl list-timers | grep certbot

# What do I have, and when does it expire?
sudo certbot certificates

# Rehearse a renewal against the staging server, without issuing anything
sudo certbot renew --dry-run

Why renewals fail

The first issuance worked, so why would a renewal fail months later? Because something around it changed:

  • Port 80 got closed. Someone tightened the firewall or security group to "HTTPS only". HTTP-01 needs port 80 reachable, even if it only redirects to HTTPS.
  • A rule blocks the challenge path. A new redirect, a maintenance mode page, basic auth on the whole site, or a framework route that swallows /.well-known/.
  • DNS moved. The domain now points at a CDN or a new load balancer, so the challenge request never reaches the server running certbot.
  • The DNS API token expired for DNS-01 setups, or was rotated without updating the config.
  • The certificate renewed, but nobody reloaded the web server. The new file is on disk; Nginx is still serving the old one from memory. This is the sneakiest one.

For that last one, use a deploy hook, which only runs after a successful renewal:

sudo certbot renew --deploy-hook "systemctl reload nginx"

Or drop an executable script in /etc/letsencrypt/renewal-hooks/deploy/, so every future renewal picks it up automatically.

Monitor from the outside

Here's the uncomfortable part. Let's Encrypt used to send expiry reminder emails, and many people relied on them as a safety net. They stopped sending those in 2025. If your renewal breaks today, nobody is going to warn you unless you've set something up.

The check should look at what visitors actually see, not at files on disk, because "renewed but not reloaded" passes every on-server check:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -enddate
# notAfter=...

Better still, let your uptime monitoring do it. Most uptime services can alert when a certificate is within a set number of days of expiry. Set the alert well inside the renewal window, so it only fires when automation has genuinely failed, and you have weeks to fix it calmly.

The rule: automation removes the work, not the responsibility. Automate the renewal, then monitor the expiry date from outside your server. One without the other is a time bomb with a long fuse.

A five-minute checklist

  • Confirm the renewal timer or cron job exists on every server that has certificates.
  • Run certbot renew --dry-run after any firewall, DNS or web server change.
  • Add a deploy hook that reloads your web server.
  • Add an external certificate expiry check with an alert.
  • Write down which method each domain uses (HTTP-01 or DNS-01) and where any DNS API token lives.

The Let's Encrypt challenge types page is a good, short read if you want the official details.

Have you ever been caught by an expired certificate? I'm curious which cause got you: the firewall, the DNS move, or the missing reload.

Comments (0)
Leave your review

Thanks for your valuable comments. Your comments has been updated and appreciate your getting in touch...

01. About Shiroz

Mohammed Shiroz

Hi, I'm Mohammed Shiroz, a software engineer and AI enthusiast from Sri Lanka who turns ideas into intelligent, real-world solutions. With over 9 years of hands-on experience, I currently lead real estate ERP development at Kate Group, a...

03.My Projects

04. Categories

Ready To order Your Project ?

Get in Touch
Close