All work

Reliability & Automation

Certificates Without Surprises

One component issues certificates. Another counts every certificate on the box that owns it and proves the renewed one is what clients actually receive.

Designed, built, and operateBashOpenSSLcertbotCaddycPanel AutoSSLresticPrometheus
  • 49 certificates inventoried on the hosts that own them, every morning, with none unclassified and no host unreachable.
  • Renewal starts at 25 days. A certificate that reaches 14 has survived about 11 daily attempts, so that page means stuck, not close.
  • The backed-up key material is restored and checked every week. It passed on October 18.

The problem

Certificate expiry is the outage everyone sees coming and it still happens, because the number people watch is rarely the certificate that expires. Behind a CDN, a public check sees the CDN's certificate. A renewer can report success while the service keeps the old one in memory.

Two incidents in one August week showed me the fix wasn't more automation. A guardrail built to prevent a mail certificate outage caused one, and a rollback reinstalled an older certificate over a good one.

One thing issues certificates

I was asked for "auto-renew anything under 29 days." A three-reviewer committee measured the fleet and turned it down. Every renewer here already triggers around 29 or 30 days, so at 29 you can't tell a renewal in progress from a broken one. Two daily actuators would also share one Let's Encrypt bucket: five duplicate certificates per rolling week, used up in about two and a half days by two force-renewals a day. That was the August 4 mail outage. The same certificate carried the alerting system's outbound mail, so 174 notifications were dropped over about seven hours and nothing reported it.

So one script issues. Every morning it renews anything under 25 days, warns at 21 and pages at 14, holding a lock the guardian shares. Success is judged by re-reading certificates after the action, never by its exit code.

The 83-day certificate that had 24

Right after issuing, in the same run and under the same lock, a guardian takes inventory. It was built to kill this false green.

verdict: 49 certs · min=38d (<host>/<name>) · 0 within 29d · 0 orphans (+0 kept by decision) · 0 propagation drift · 0 unclassified · 0 unreachable
stalled renewers: none (no managed-auto cert below 25d)
The guardian's verdict from the October 19 run. Only the name of the nearest certificate is replaced.

A healthy number pointed at the wrong certificate

On August 9, the certificate metric looked fine for the shared web hosting server. It wasn't measuring that server.

  1. MetricThe expiry check probed each public hostname and recorded 83 days left for one site and 89 for another.
  2. On the boxThe hosting server itself was serving certificates with 24 and 30 days left.
  3. WhyThe probe always got Cloudflare's edge certificate. 53 sites on that server, the closest expiries on the fleet, were hidden behind a healthy number.
  4. The runbookIt already said this class of bug was fixed. It wasn't.
  5. The fixInventory is now taken on the box that owns each certificate, from every certificate store on the box: ACME clients, web servers, the hosting panel, mail and internal PKI. The public probe is now one input.

Every certificate is mapped to the mechanism that renews it. One with no mechanism is a finding, and an unreachable host is reported, never skipped.

A broken renewer is a different alert

On August 14 a client site was 19 days from expiry while AutoSSL logged "Ready for Renewal" every three hours for 71 days. The expiry alert was working, and it said the wrong thing. The real cause was that Let's Encrypt couldn't reach the server through a firewall that only admits Cloudflare.

So an auto-renewed certificate under 25 days is now reported as a stalled renewer, separately from expiring. The headline minimum also leaves out certificates that serve no traffic, like stale lineages left behind by a migration, because a minimum set by a dead certificate is wrong in both directions.

Proof it's what clients get

A file copy that succeeds while the service holds the old certificate in memory is the August 8 failure. So the guardian compares the SHA-256 fingerprint of the file on disk with the one served over a live handshake. Mail is checked on all three TLS ports, because the daemons reload independently. The TURN relay caches its certificate at start with no hot reload, so a file-only check there would pass for about 60 days over a stale wire.

The check gates on whether it parsed a certificate, never on the exit code. Origins that require client certificates abort the handshake and exit non-zero while perfectly healthy.

Backups that get restored

Key material is backed up nightly as its own snapshot, and every Sunday a self-test restores it: keys parse, each key matches its certificate, the backed-up mail certificate is the one being served. In August a negative test caught the test itself: with both files missing, it hashed two empty inputs, got matching hashes, and passed. It now parses before it compares.

PASS origin key restores and parses
PASS restored key matches restored cert
PASS certbot ACME account key restored
PASS wazuh root CA + admin key restore and parse
PASS coturn key restores and matches its cert
SELFTEST PASSED
Most of the October 18 self-test. Two lines that name a host or a port are left out, and so is the snapshot id.

What it doesn't do

Wire proof covers the mail ports and the TURN relay. Everything else is checked at the source, not fingerprinted off the wire. The guardian can re-sync a drifted copy, but the scheduled run is report-only, so drift gets a person.

Cloudflare Origin CA certificates last 15 years and have no renewal mechanism. Cloudflare shows the private key once, so they're flagged for manual reissue. The secrets vault's own certificate is on a list no automation may touch: renewing it restarts the vault, the vault comes back sealed, and the regulated portals pause their encrypted features until a person enters three of the five key shares.

Engineering decisions

The calls I made, and what each one cost.

One actuator issues. The guardian only reports.

Two actuators sharing one rate-limit budget is how the August 4 outage happened. I accepted a slower response to drift in exchange for one ladder that can't fight itself.

Renew at 25 days, page at 14.

Reaching 25 means the certificate's own renewer has already failed. That leaves 11 daily retries before anyone gets paged.

No automatic rollback to the previous certificate.

"Roll back on failure" is the August 8 incident word for word. A rollback that reinstalls an older certificate turns a renewal problem into an expiry.

More systems

I'm looking for Incident Commander, SRE and AIOps roles.

If your team is drowning in toil, alert noise, or incidents that never quite close. That is the work I do.

Get in touch