SSL Expired Despite Auto-Renewal: Check Delivery, Expiry and Cloudflare's Origin
An enabled renewal task is not evidence that clients receive a fresh certificate. Follow the path from issuance to the TLS endpoint and check each boundary.
Monitor the certificate being served, not only the renewal timer
An enabled renewal timer is a plan to run software. A renewed certificate on disk is an artifact. A valid certificate presented to a client is the result you need. These are three different observations, and failures can occur between them.
Begin with the affected hostname and the path a browser takes to it. If a CDN terminates public TLS, the visitor sees the CDN's edge certificate. The connection from the CDN to your server is a separate TLS hop with its own certificate, configuration and trust relationship.
That distinction matters behind Cloudflare. A healthy public certificate does not establish that the origin certificate is healthy. Cloudflare's Full (strict) documentation (opens in a new tab) describes verification of the origin connection separately from the visitor-facing connection.
Check the public endpoint with hostname verification
On a Linux diagnostic machine with OpenSSL and the timeout utility, the following performs a bounded connection. Replace the hostname consistently:
timeout 15s openssl s_client \
-connect example.com:443 \
-servername example.com \
-verify_hostname example.com \
-verify_return_error </dev/null
SNI selects the intended virtual host. Hostname verification and certificate-chain verification address different requirements. Review the diagnostic output and command status; do not turn an unverified handshake into a passing monitor just because it printed a certificate. The OpenSSL s_client manual (opens in a new tab) documents these controls.
Run this from a location relevant to the failure. Different DNS answers, IPv4 and IPv6 paths, or inconsistent edge configuration can lead different clients to different endpoints. Preserve which address and certificate were observed.
Separate expiry from identity and trust
If you already have a PEM certificate file from an authorized diagnostic or your renewal tooling, inspect its dates and an explicit warning horizon:
openssl x509 -in certificate.pem -noout -subject -issuer -dates
openssl x509 -in certificate.pem -noout -checkend 1209600
The second command checks a fourteen-day horizon in seconds. A nonzero result requires attention, including checking for file or parsing errors. This test alone does not verify the hostname, trust chain or which certificate a live service is presenting. See the OpenSSL x509 reference (opens in a new tab).
In an isolated experiment, a synthetic one-day certificate failed a two-day checkend horizon, while a synthetic 365-day certificate passed it. No real ACME issuance or production renewal was performed. The experiment verified the expiry-test behavior only.
Choose alert horizons that give your team time to respond. A short-lived certificate needs a renewal-aware policy; assuming every certificate has the same lifetime creates misleading alerts. Monitor repeated renewal failure as well as the eventual expiry boundary.
Trace the renewal pipeline one stage at a time
When the served certificate is nearing expiry, investigate these boundaries:
| Stage | Evidence to inspect |
|---|---|
| The renewal task was scheduled | Timer or cron configuration and recent execution |
| The certificate authority validated the domain | Renewal logs and the selected challenge method |
| New files were written | The renewed certificate's dates and configured lineage |
| The server loaded those files | Its configured certificate paths and successful reload |
| Traffic reaches that server | A new connection through the actual public or origin path |
For a Certbot-managed server, commands such as certbot certificates and certbot renew --dry-run are useful diagnostic tools. A dry run contacts the staging certificate authority and can invoke hooks or temporary web-server changes. Schedule it appropriately; it is not a purely read-only local inspection.
Certbot's renewal guide (opens in a new tab) distinguishes renewal attempts from deploy hooks after successful renewal. Review the hook that reloads the actual TLS terminator. A host Nginx reload will not update a different container or load balancer that serves the certificate.
Check the origin without opening it to the world
Use an authorized path to the origin from your infrastructure or an existing monitoring location. Do not disable Cloudflare proxying or widen a firewall simply to make an external checker reach it. A direct-origin test needs the intended SNI, hostname and CA trust for that deployment.
Cloudflare Origin CA certificates are intended for the Cloudflare-to-origin connection and are not generally trusted by ordinary browsers. A direct browser trust warning can therefore reflect the selected trust model rather than an expired certificate. Cloudflare explains this in its Origin CA documentation (opens in a new tab).
Do not bypass verification with an insecure-client flag and call the result healthy. When a private or Origin CA trust anchor is appropriate, configure it explicitly for that controlled diagnostic. Keep public-edge and origin results separate in reports.
DeployWatchers' public SSL check follows the public hostname. For a proxied hostname that normally means observing the edge. Keep an additional internal or infrastructure-level origin check if you need evidence about the hidden hop.
Verify delivery after fixing renewal
After a successful renewal and the intended reload, establish a new TLS connection and compare the served certificate's identity and dates with the replacement. Repeat the check against each relevant termination point or replica where your architecture requires it.
Keep the timer, renewal logs and expiry alerts as complementary signals. One tells you the automation is configured, another shows what it attempted, and the served-certificate check shows what clients can actually use. None of them is a substitute for the others.
Catch problems after your next deployment
Monitor availability, browser JavaScript errors and visual changes with DeployWatchers.