Guide

How to monitor SSL certificate expiry across client sites

Most sites renew their certificates automatically. Certificates still expire. This guide shows how to check one site by hand, how to check a list of client sites with a short script, and when to send notices.

Why certificates still expire with auto-renewal

Auto-renewal removes most manual work. It does not remove the need to check. Common causes of an expired certificate:

  • The renewal job fails without a warning. A DNS change, a redirect or a firewall rule can block the ACME challenge. A server move can drop the scheduled job.
  • The new certificate is not deployed. The web server was not reloaded, or a CDN or load balancer still serves the old certificate.
  • A safety net is gone. Let's Encrypt ended its expiration notification emails on 4 June 2025. If you relied on those emails, nothing warns you now.
  • Certificates renew more often. Under a CA/Browser Forum ballot, the maximum lifetime of a public TLS certificate dropped to 200 days on 15 March 2026. It drops to 100 days on 15 March 2027 and to 47 days on 15 March 2029. More renewals give more chances for one to fail.

What to check: expiry, chain and hostname

An expiry date alone is not enough. Check three things:

CheckWhat goes wrongWhat the visitor sees
ExpiryThe certificate passed its notAfter date.A full-page browser warning.
ChainThe server does not send the intermediate certificate.Some browsers and most API clients fail. Others work, so the problem hides.
HostnameThe certificate does not cover the hostname, for example www is missing.A browser warning on that hostname only.

Check one site by hand

In the browser. Open the site and click the icon next to the address. Open the certificate details and read the expiry date. This is fine for one site. It does not scale.

With openssl. These commands were tested on 8 November 2026 with OpenSSL 4.0.3. The -enddate and -checkend commands also work with LibreSSL 3.3.6, which macOS ships. Replace example.com with the hostname. Always pass -servername, because servers that host many sites choose the certificate by that name (SNI).

Show the expiry date:

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

The output looks like notAfter=Dec 25 22:56:35 2026 GMT.

Show the subject, the issuer, both dates and the hostnames that the certificate covers:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

Test whether the certificate expires within 14 days (1,209,600 seconds). The exit code is 0 when it does not and 1 when it does, so you can use it in scripts:

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

Check the chain and the hostname together:

echo | openssl s_client -connect example.com:443 -servername example.com \
  -verify_hostname example.com 2>/dev/null | grep 'Verify return code'

Verify return code: 0 (ok) means the chain and the hostname are valid. Other codes that we saw in tests:

  • 10 (certificate has expired)
  • 21 (unable to verify the first certificate): the intermediate certificate is missing.
  • 62 (hostname mismatch)

Check a list of client sites with a script

Put one hostname per line in hosts.txt. This POSIX shell script prints each expiry date and flags certificates that expire within 30 days:

#!/bin/sh
while read -r host; do
  cert=$(echo | openssl s_client -connect "$host:443" -servername "$host" 2>/dev/null)
  end=$(printf '%s\n' "$cert" | openssl x509 -noout -enddate | cut -d= -f2)
  if printf '%s\n' "$cert" | openssl x509 -noout -checkend 2592000 >/dev/null; then
    result="ok"
  else
    result="EXPIRES IN 30 DAYS OR LESS"
  fi
  echo "$host | $end | $result"
done < "$1"

Run it with sh check.sh hosts.txt. Example output:

example.com | Dec 25 22:56:35 2026 GMT | ok
expired.badssl.com | Apr 12 23:59:59 2015 GMT | EXPIRES IN 30 DAYS OR LESS

The script checks expiry only. Add the -verify_hostname command above if you also want chain and hostname results. A host that does not answer prints an empty date and is flagged, so check those lines by hand.

Where spreadsheets, calendars and scripts break

A spreadsheet of expiry dates or a calendar reminder works for a few sites. It breaks as the client list grows:

  • Auto-renewal changes the date every few months, so the sheet goes stale.
  • Nobody updates the sheet when a client adds a subdomain or moves to a CDN.
  • A script on a laptop runs only when someone remembers to run it.
  • A cron job that emails its output fails silently when the email stops arriving.
  • Nobody owns the reminder when a colleague is on leave.

At that point you need a check that runs on its own, from outside your network, and reports to a shared place.

Choosing notice days

Pick notice days that give you time to act, but not so many that people ignore them:

  • 30 days: time to find out who controls the certificate and to fix a broken renewal.
  • 14 days: the renewal should have happened by now. Treat this as an issue to fix.
  • 7 days: last call. Escalate.

Send the notices as one daily summary, not as one alert per certificate. A team that looks after 40 client sites reads one morning list. It does not read 40 separate emails. Keep instant alerts for real failures, such as a certificate that has already expired or a broken chain.

Monitoring SSL certificate expiry with Pingtier

Pingtier checks expiry, chain and hostname on every HTTPS monitor. It sends notices at 30, 14 and 7 days in one daily digest at 08:00 in your organisation's time zone. At 14 days or less, an SSL issue opens on the Today list. Each certificate is tied to a client. Pingtier opens as a free beta soon. Free during beta. Then EUR 4 per client a month, excl. VAT.

See SSL certificate monitoring, website monitoring for agencies or website and SSL monitoring for MSPs. For the basics of uptime checks, read what is uptime monitoring.

FAQ

Why do I need -servername in the openssl command? Many servers host several sites on one IP address. They choose the certificate by the name that the client sends (SNI). Without -servername you may see the wrong certificate.

If I use auto-renewal, do I still need SSL expiry monitoring? Yes. Renewal jobs fail, and renewed certificates are not always deployed. Monitoring tells you when the certificate that visitors actually see is close to expiry.

How many days before expiry should I get a notice? 30, 14 and 7 days is a common pattern. 30 days gives time to fix a broken renewal, 14 days marks a real issue, and 7 days is the last call.

What is a certificate chain error? The server does not send the intermediate certificate that links its certificate to a trusted root. Some browsers fill the gap, but many API clients and older devices fail.

How often should I check? At least once a day for expiry. Check chain and hostname every time the site changes its server, CDN or certificate.