How to Track SSL Certificate Expiry Dates in Bulk
Manage SSL certificate expiry dates across dozens or hundreds of certificates. Methods from scripts to dedicated monitoring tools for teams of every size.
One certificate is easy to track. You know the domain, you know when it expires, you renew it when the time comes. But nobody manages just one certificate. You've got the main site, the API, staging environments, client microsites, internal tools, mail servers, and that legacy app nobody wants to touch. Across different servers, different CAs, and different teams. When you have 20, 50, or 200 certificates, manual tracking isn't just inefficient -- it's a guarantee that something will expire without warning.
The Scaling Problem
Certificate management doesn't scale linearly. Every certificate you add creates multiple tracking obligations:
- Expiry dates spread across different renewal windows (90 days for Let's Encrypt, 1 year for commercial certs)
- Multiple CAs with different portals, different renewal flows, and different validation requirements
- Multiple servers where the same certificate might be installed (web server, load balancer, CDN, reverse proxy)
- Multiple teams where no single person knows about every certificate
- Shadow certificates that someone deployed six months ago and nobody documented
At 5 certificates, you can keep this in your head. At 20, you need a system. At 50+, anything short of automated monitoring is a liability.
Method 1: The Spreadsheet
The simplest approach. A shared spreadsheet (Google Sheets, Excel) with columns for domain, issuer, expiry date, server location, and renewal owner.
Pros
Cons
Breaks at: 15-20 certificates. Once you're past that, someone will forget to update the sheet after a renewal, the dates will drift from reality, and you'll be back to surprised-by-expiry territory.
A spreadsheet is better than nothing. But it's a documentation tool, not a monitoring tool. It records what you believe to be true, not what is actually true.
Method 2: Shell Script with OpenSSL
For the engineering-minded, a bash script that checks certificates in a loop is a big step up from a spreadsheet.
#!/bin/bash
# check-certs.sh - Check SSL certificate expiry for a list of domains
DOMAINS=(
"example.com"
"www.example.com"
"api.example.com"
"staging.example.com"
"app.example.com"
)
WARN_DAYS=30
WARN_SECONDS=$((WARN_DAYS * 86400))
for domain in "${DOMAINS[@]}"; do
expiry=$(openssl s_client -connect "$domain:443" -servername "$domain" </dev/null 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "$expiry" ]; then
echo "ERROR: Could not connect to $domain"
continue
fi
expiry_epoch=$(date -d "$expiry" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$expiry" +%s 2>/dev/null)
now_epoch=$(date +%s)
days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
if [ "$days_left" -lt 0 ]; then
echo "EXPIRED: $domain expired $((days_left * -1)) days ago ($expiry)"
elif [ "$days_left" -lt "$WARN_DAYS" ]; then
echo "WARNING: $domain expires in $days_left days ($expiry)"
else
echo "OK: $domain expires in $days_left days ($expiry)"
fi
done
Run this via cron daily and pipe the output to email or a Slack webhook.
Pros
Cons
Breaks at: 30-50 certificates. Script maintenance becomes a job in itself. Adding new domains requires editing the script. Error handling for edge cases (timeouts, SNI issues, non-standard ports) grows the script beyond what anyone wants to maintain. And when the cron server itself has issues, nobody gets alerts about anything.
Method 3: Infrastructure Monitoring Plugins (Nagios, Zabbix, Prometheus)
If you already run infrastructure monitoring, SSL certificate checks can be added as plugins or exporters.
Nagios: The check_ssl_cert plugin monitors certificate expiry and chain validity. Configure it as a service check for each domain.
Zabbix: Built-in web scenarios and the zabbix-ssl-check template can monitor certificate expiry. Integrates with Zabbix's alerting system.
Prometheus: The ssl_exporter or blackbox_exporter with the tls prober scrapes certificate metrics (expiry timestamp, chain length, issuer). Pair with Grafana dashboards and Alertmanager for notifications.
# Prometheus blackbox_exporter config for SSL checks
modules:
tls_connect:
prober: tcp
tcp:
tls: true
tls_config:
insecure_skip_verify: false
Pros
Cons
Breaks at: It doesn't really break at scale -- these tools handle thousands of checks. But the overhead of maintaining the monitoring infrastructure itself is significant. If you're setting up Prometheus just for SSL checks, you're using a sledgehammer to hang a picture frame.
Skip the infrastructure overhead
Purpose-built SSL monitoring. Add domains, get alerts. No servers to maintain.
Method 4: Dedicated SSL Monitoring Tools
Purpose-built SSL monitoring tools are designed specifically for tracking certificate expiry across many domains. They handle the problems that scripts and spreadsheets can't.
What a good SSL monitoring tool provides:
Automatic certificate discovery
Escalating alerts
Multi-channel notifications
Dashboard with sorting and filtering
Chain and configuration validation
No infrastructure to maintain
Comparing the Approaches
| Approach | Cost | Setup Time | Auto-Alerts | Chain Checks | Scales To |
|---|---|---|---|---|---|
| Spreadsheet | Free | Minutes | No | No | ~15 certs |
| Shell script + cron | Free | Hours | Basic (email) | No | ~50 certs |
| Nagios/Zabbix/Prometheus | Free (self-hosted) | Days | Yes | Yes (with plugins) | Thousands |
| Dedicated SSL monitoring | Free-$9/mo | Minutes | Yes (escalating) | Yes | Unlimited |
What to Look For in a Bulk SSL Tracking Solution
If you're evaluating tools, here's what matters for bulk certificate management:
Must-haves:
- Easy bulk import (paste a list of domains, not one-by-one entry)
- Expiry-sorted dashboard (the certificate expiring soonest should be at the top)
- Configurable alert thresholds (30, 14, 7 days -- not a fixed single warning)
- Team notification channels (not just the person who set it up)
- Chain validation (catch missing intermediates, not just expired leaves)
Nice-to-haves:
- Certificate change detection (alert when a certificate is replaced unexpectedly)
- Historical tracking (see when certificates were renewed, who changed what)
- API access (integrate with your deployment pipeline)
- Tag/group management (organize certificates by team, environment, or project)
The Real Cost of Not Tracking
When a certificate expires unexpectedly on a production site:
- Revenue loss: E-commerce sites lose every transaction during the outage. Visitors see "Your connection is not private" and leave.
- SEO impact: Google deindexes pages that return SSL errors. Recovery takes days or weeks.
- Trust damage: Customers who see a security warning may not come back, even after the issue is fixed.
- Engineering cost: Emergency renewals at 2 AM involve the most expensive, least productive engineering hours.
The cost of any tracking solution -- even the most expensive one -- is trivial compared to a single certificate expiry incident. The question isn't whether you can afford monitoring. It's whether you can afford not having it.
Pick the approach that matches your scale. If you have 5 certificates and one server, a cron script is fine. If you have 50 certificates across multiple teams and environments, invest in a proper monitoring tool. Either way, have something -- because the spreadsheet you never update is the same as having nothing at all.
Related Articles
One expired certificate is an incident. Two is a pattern. Three is a missing process.
Never miss an SSL certificate expiry
Monitor your certificates and get alerts before they expire. Free for up to 3 certificates.