Safeguard
Developer Tools•

How do you check certificate expiry with openssl in a cron job?

Use openssl x509 with the checkend option to exit nonzero when a certificate expires within N seconds. A cron script, its limits and a better probe.

Safeguard Security Team
4 min read

Run openssl x509 with the checkend option and a number of seconds. It exits with zero if the certificate will still be valid after that many seconds and nonzero if it will expire. Wrap it in a cron job against the live endpoint, alert on a nonzero exit, and treat it as a minimum, not a full monitoring system.

What checkend does

The OpenSSL manual describes checkend as checking whether the certificate expires within the next arg seconds, exiting nonzero if it will expire and zero if not. With the multi option it checks every certificate in the input and fails if any will expire in that time. That makes it useful for a bundle file that contains a chain.

Check the certificate the server actually presents

A file on disk can be fine while the server still serves an older certificate from memory. Probe the endpoint instead. The command below fetches the served certificate and tests whether it lasts at least 14 more days (1209600 seconds).

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -checkend 1209600

The servername value matters because a server may choose its certificate by SNI. See wrong certificate served because of SNI and debugging with s_client.

A small cron script

#!/bin/sh
host="$1"; days="${2:-14}"; secs=$((days*86400))
if ! echo | openssl s_client -connect "$host:443" -servername "$host" 2>/dev/null \
   | openssl x509 -noout -checkend "$secs" >/dev/null; then
  echo "Certificate for $host expires within $days days or could not be read" \
   | mail -s "TLS expiry warning: $host" ops@example.com
fi

A failed connection also gives a nonzero exit, which this script reports. That is deliberate: an unreachable or broken endpoint should raise the same alarm.

Choosing thresholds

WindowUse
21 to 30 daysEarly warning for 90 day certificates renewed at about 30 days left
14 daysWarning that renewal has stalled
7 daysPage a person
HoursFor six day certificates

Match the thresholds to your renewal setting. See why Let's Encrypt emails are gone.

Limits of this approach

  • It checks expiry only. It does not check the chain, hostname match or revocation.
  • It tests one port and one name per call. Loop over every name you serve.
  • It runs from one place. A certificate can differ by region or load balancer node, so probe from outside too.
  • Cron mail depends on a working mail setup. Send to your real alerting tool.

For wider coverage, use a probe that exposes the expiry as a metric, so you can graph and alert on it with the rest of your monitoring.

Steps

  1. List the hostnames and ports to test.
  2. Save the script and run it by hand against a known good and a known expired test endpoint.
  3. Schedule it in cron to run daily.
  4. Route failures to your alert channel, not a personal inbox.
  5. Add a heartbeat so you know the job itself is still running.

Where Safeguard fits

Safeguard does not monitor certificate expiry. It provides continuous monitoring of dependencies, plus SBOM scanning and policies. The demo shows how ongoing checks surface new findings.

Try it yourself

Click through it at your own pace, or open it full screen.

Notice the difference between a one time scan and checks that keep running on a schedule.

Quick check

What does a nonzero exit mean?

The certificate will expire within the number of seconds you passed to checkend.

Can it check a whole chain?

Yes, with the multi option it checks every certificate in the input and fails if any of them will expire in time.

Is this enough for production monitoring?

It is a good floor. Add chain and hostname checks and alerts that go to your on-call system.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.