How to monitor SSL certificate expiry across many client sites

The problem

If you look after many client websites, one expired certificate is enough to turn a site "Not Secure" and bring a client on the phone. Most of these certificates auto-renew, so nobody watches them. That's exactly why a failed renewal goes unnoticed until a visitor sees the warning.

It's also getting more frequent. Under CA/Browser Forum ballot SC-081, publicly trusted certificates have been capped at 200 days since 15 March 2026. The cap falls to 100 days in March 2027 and 47 days in March 2029 (timeline summary). Shorter lifetimes mean more renewals per site per year, and more chances for one to fail.

What you want is simple: one list of every domain with its days to expiry, and a warning early enough to fix a problem. Here are four ways to get it, from free and manual to fully automatic.

Option 1: Calendar reminders

Check each certificate once (see [how to check when an SSL certificate expires](/lapsewatch/guides/check-ssl-certificate-expiry)) and add a calendar event about 14-30 days before each expiry date.

Option 2: A shared spreadsheet

Keep one row per hostname with these columns: domain, client, host, issuer, auto-renew?, expires, days left. In Google Sheets or Excel, =C2-TODAY() gives days left, and conditional formatting can turn rows red under 14 days.

Tip: list every hostname a visitor might reach, not just the main domain. Include www, the bare domain, shop and booking subdomains, and staging sites that clients actually use.

Option 3: A script that checks every domain

Put your hostnames in domains.txt, one per line, and run this on Linux or WSL (it uses GNU date):

`bash

#!/usr/bin/env bash

while read -r d; do

[ -z "$d" ] && continue

end=$(echo | timeout 10 openssl s_client -connect "$d:443" -servername "$d" 2>/dev/null \

| openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)

if [ -z "$end" ]; then echo "ERROR $d"; continue; fi

days=$(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 ))

echo "$days $d"

done < domains.txt | sort -n

`

The output is sorted with the soonest expiry at the top. Run it from cron every morning and pipe lines under a threshold, such as 21 days, to email or a Slack incoming webhook.

- The -servername flag is essential on shared hosting. Without it you may get the server's default certificate and the wrong date.

- Treat ERROR lines as alerts. A site that doesn't answer on 443 is its own problem.

- Somebody has to own the script. If the server it runs on goes away, monitoring stops silently. Have it send a short "all OK" summary every week, so you notice when the messages stop.

- On macOS, date -d doesn't exist. Use date -j -f "%b %d %T %Y %Z" "$end" +%s instead.

Option 4: A monitoring tool

Many uptime monitors include SSL expiry checks. For example, UptimeRobot runs SSL and expiry checks on HTTPS monitors. Its help center says the check runs once every 24 hours and that alert timing depends on the issuer. If you already pay for uptime monitoring on every client site, turning on its SSL checks may be all you need.

When comparing tools, ask:

A setup that works

Whichever option you choose, the same basics apply:

1. Inventory: one source of truth for every client hostname. The spreadsheet in Option 2 works.

2. Automatic checking: a script or tool that reads the real certificate daily. Don't rely on remembered dates.

3. Two alert levels: an early heads-up (around 21-30 days) and an urgent one (around 7 days).

4. A shared destination: alerts go to a channel the whole team sees.

5. A fix path: for each host, know where the certificate is managed (cPanel AutoSSL, Let's Encrypt via Certbot, the CDN, or a paid certificate authority).

Where Lapsewatch fits

We're building Lapsewatch for agencies and freelance admins with many client domains. You'll paste in your domains once, and it will keep one list sorted by days to expiry and send an email or Slack ping before any certificate lapses. It won't renew certificates for you. It's the warning, not the fix. If you already run an uptime monitor with SSL checks, or are happy maintaining the script above, those are perfectly good choices too.

Try it