Home/Server & Website Managed Operations/How to Detect Certificate Expiry Early: Review of Monitoring Scripts, Alerts, and Auto-Renewal Failures
Server & Website Managed Operations

How to Detect Certificate Expiry Early: Review of Monitoring Scripts, Alerts, and Auto-Renewal Failures

Certificate expiry is the most preventable incident in operations—it is entirely predictable, with the expiration time explicitly stated in the certificate. Yet it still happens frequently, not because people “forgot,” but because they “assumed auto-renewal was handling it, when in fact it had failed long ago”.

Therefore, monitoring must address two issues: how many days remain until expiry, and whether auto-renewal is still functioning. The second point is more critical than the first.

Checking Remaining Certificate Days

# Local certificate file
openssl x509 -in /path/fullchain.pem -noout -enddate

# Convert to remaining days
openssl x509 -in /path/fullchain.pem -noout -enddate | 
  awk -F'=' '{cmd="date -d "$2" +%s"; cmd|getline e; close(cmd);
              print int((e-systime())/86400)" days"}'

# Online check (checks the actually effective certificate, which is more reliable)
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null 
  | openssl x509 -noout -enddate

Prioritize online checks. Local files may be outdated, or nginx reload failures may mean the effective certificate hasn’t been updated—the online check shows the certificate users will actually encounter.

Bulk Check Script

#!/bin/bash
# /root/check-cert.sh
DOMAINS="example.com www.example.com api.example.com"
WARN_DAYS=30
ALERT=0

for d in $DOMAINS; do
  end=$(openssl s_client -connect "$d:443" -servername "$d" </dev/null 2>/dev/null 
        | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
  if [ -z "$end" ]; then
    echo "[$d] Connection failed or certificate retrieval failed"
    ALERT=1
    continue
  fi
  left=$(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 ))
  echo "$d  Remaining ${left} days  (Expires $end)"
  [ "$left" -lt "$WARN_DAYS" ] && ALERT=1
done

exit $ALERT
chmod +x /root/check-cert.sh
/root/check-cert.sh; echo "Exit code $?"

Integrating Cron Jobs and Alerts

# Run once a day
0 10 * * * /root/check-cert.sh >> /var/log/cert-check.log 2>&1 
  || echo "Certificate Alert" | mail -s "Certificate Expiring Soon" ops@example.com

The || here is key: the script uses its exit code to indicate whether an alert is needed, so cron only triggers notifications when the exit code is non-zero. This prevents receiving useless emails daily.

Part 2: Confirming Auto-Renewal is Still Alive

Using tools like acme.sh doesn’t mean everything is fine. Renewal can fail for various reasons:

  • The port 80 dependency for validation has changed (e.g., after a site-wide 301 redirect, the validation path becomes unreachable)
  • DNS validation API credentials have expired
  • Cron jobs were lost due to system reinstallation/migration
  • Renewal succeeded but nginx wasn’t reloaded, so the old certificate is still in use
# ① Confirm renewal task exists
crontab -l | grep acme

# ② Check renewal logs
tail -50 ~/.acme.sh/acme.sh.log

# ③ Manually run once (--force forces execution, used to verify the process works)
acme.sh --renew -d example.com --force

# ④ Crucial: Confirm new certificate is loaded (compare file update time with actual effective certificate)
ls -l ~/.acme.sh/example.com/fullchain.cer
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null 
  | openssl x509 -noout -dates

Step ④ is the core of the entire monitoring strategy. If renewal succeeds but isn’t reloaded, the certificate file updates while the effective one remains old—in this case, “the certificate file is new” gives you a false sense of security.

Comparison of Three Monitoring Methods

Method Advantages Limitations
Local script + cron Controllable, no cost Fails when the server itself goes down
External monitoring service Independent of your servers Requires third-party accounts
Cloud provider alerts Simple configuration Limited coverage

We recommend having at least one external channel. Relying solely on cron on the server is equivalent to “letting the monitored object report its own status”—if the machine crashes or cron stops, alerts disappear too.

Decision Tree

Establish Certificate Monitoring
├─ Online check of remaining days (check the actually effective certificate, not local files)
├─ Script uses exit codes to indicate alert needs → Use || in cron to trigger notifications
├─ At least one external monitoring channel (avoid alert failure due to server-side issues)
└─ If using auto-renewal, separately monitor the "renewal mechanism":
   ├─ Is the task still in crontab?
   ├─ Are there errors in renewal logs?
   └─ Is the new certificate truly loaded? (Compare file dates with actual effective certificates)

Remaining Days Alert Thresholds
├─ < 30 days → Time to handle
├─ < 7 days  → High priority
└─ Expired   → Immediate action

Scenario Walkthrough: Discovering Certificate Expiry on the Day It Happens, via User Reports

Symptom: A site’s certificate was found invalid on its expiration day,
and the first to know wasn’t operations, but rather through external feedback.

  1. First, figure out why no one noticed early → There was no internal check for “remaining days”;
    all alerts were based on availability; and before expiry, the site remained accessible normally,
    so availability monitoring showed no reaction.
  2. Identify the common trait of such incidents: no pre-incident symptoms → Everything worked fine before expiry,
    so availability monitoring showed no reaction.
  3. Add independent day-count detection → Directly fetch the certificate’s end date, calculate remaining days,
    and alert if below threshold. This check must not depend on whether renewal succeeded.
  4. Apply detection across multiple domains → For subdomains or multiple sites, check each individually;
    don’t just check the main domain.
  5. Incorporate into daily tasks with tiered alerts → Set reminders well in advance,
    and urgent alerts as expiry approaches, leaving a window for remediation.
  6. Conduct a drill to confirm alerts actually arrive → Temporarily raise thresholds to verify end-to-end alert chain functionality.
# Directly fetch end date and convert to remaining days
end=$(echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null 
  | openssl x509 -noout -enddate | cut -d= -f2)
echo "Remaining days: $(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 ))"

# Check multiple domains individually
for h in example.com a.example.com b.example.com; do
  printf '%-24s ' "$h"
  echo | openssl s_client -connect $h:443 -servername $h 2>/dev/null 
    | openssl x509 -noout -enddate
done

# Alert channel self-test—must verify receipt after configuration
curl -sS -X POST alert_channel_url -d 'text=Certificate expiry self-test (ignore)' -o /dev/null -w '%{http_code}n'

Root Cause: Lack of independent detection for “certificate remaining days”;
all monitoring focused on availability, while certificates show no anomalies before expiry.

Two key takeaways:

  • Availability monitoring cannot detect certificate expiry; remaining days must be checked separately.
    By the time availability monitoring triggers, the incident has already occurred; only separate checks provide early warning.
  • This check must not share the same pipeline as auto-renewal.
    Renewal itself can fail silently; only directly reading the certificate’s end date provides an independent, reliable basis.

8 Common Pitfalls

  1. Only checking local certificate files: May differ from the actually effective certificate.
  2. Ignoring auto-renewal after setup: Renewal failures are silent.
  3. Renewal succeeds but no reload: Files are new, but old ones are still in use.
  4. Monitoring scripts sending alerts daily: Should use exit codes to trigger only when necessary.
  5. Only server-internal monitoring: Fails together with the server during outages.
  6. Thresholds set too low: Alerting with only 3 days left leaves insufficient time for remediation.
  7. Monitoring only the main domain for multi-domain setups: Subdomain certificates also expire.
  8. Validation methods failing after site-wide 301 redirects: Switch to DNS validation or add exception rules.

Real Customer Feedback (From Cloud Marketplace Reviews and Inquiries for Similar Products)

The following excerpts are taken from real buyer reviews and inquiries for similar operations services on Alibaba Cloud / Tencent Cloud / Huawei Cloud cloud marketplaces (service providers include our store and competitors, provided for reference only, not fictional tickets from this site):

Xi****Gu Score: 5.0 Points 2021-11-16 15:13 Handled f****7 Score: 5.0 Points 2018-11-20 14:04

Hao****l Score: 5.0 Points 2024-07-09 16:51 x****g Score: 5.0 Points 2024-02-14 16:55 a****z Score: 5.0 Points 2020-07-16 14:00 p****2 Score: 5.0 Points 2019-10-21 14:48 He****She Score: 5.0 Points 2019-09-05 11:45 Not bad! The boss’s PY service is quite good, never seen someone deploy certificates at 3 AM…. g****n Score: 4.3 Points 2019-09-04 16:43 a****z Score: 5.0 Points 2019-08-23 17:35 3****4 Score: 5.0 Points 2019-08-06 22:33 f****j Score: 5.0 Points 2019-08-05 22:00 y****7 Score: 5.0 Points 2018-08-03 14:25

z****1 Score: 5.0 Points 2019-09-05 15:05

FREE CHECKUP

Free server checkup

We will send a problem checklist and remediation advice within one business day — no obligation to engage.

135 410 16684
Weekdays Mon – Fri 10:00 – 22:00 (UTC+8) · 7×24 emergency response
Call now
CONTACT

Contact Us

How can we help?

* Required