2:47 AM. My phone won't stop screaming.
I grabbed it with one eye still closed, already knowing something was catastrophically wrong. The PagerDuty alerts were coming in waves. Then Slack. Then email. Then clients calling my emergency line.
23 SSL certificates. All expired. All at once.
Three e-commerce sites went down mid-checkout. A SaaS platform locked out 12,000 users. A banking portal showing security warnings to customers trying to check their accounts. The damage? $2,300 in SLA penalties that night. The real cost? Trust I'd spent years building, gone in 2 hours and 47 minutes.
The worst part? I knew these certificates were expiring. I had a spreadsheet. I checked it weekly. I just... missed one week. One spreadsheet review. That's all it took.
If you've ever managed SSL certificates across multiple domains, you know this nightmare. You might be living it right now.
The Silent Killer Nobody Talks About
Here's something that should terrify you: 847,000 websites are running with expired SSL certificates right now. Today. As you read this.
And these aren't random blog sites. GitHub went down in 2023 because of an expired certificate. Spotify had a 2-hour outage in 2022. LinkedIn's mobile app stopped working for millions in 2021. Same reason: SSL expiry.
The problem isn't that engineers are incompetent. It's that manual SSL monitoring doesn't scale. Here's what I was doing:
- Excel spreadsheet with 47 domains
- Calendar reminders 30 days before expiry
- Manual checks via browser every Monday morning
- Prayer that renewal emails wouldn't hit spam
It worked... until it didn't.
The certificates that killed me that night were all Let's Encrypt 90-day certs. I had them auto-renewing via certbot, but three clients had changed their DNS configurations without telling me. Renewal failed silently. My spreadsheet showed "Auto-renewed โ". Reality showed "Expired ๐".
The Solution: 50 Lines of Python That Changed Everything
After that night, I rage-coded. Here's the exact script I built at 4 AM while on the phone with angry clients:
import ssl
import socket
from datetime import datetime
from cryptography import x509
from cryptography.hazmat.backends import default_backend
import requests
import json
def check_ssl_expiry(hostname, port=443):
"""
Connect to a domain and extract SSL certificate expiration date
Returns days until expiry (negative if already expired)
"""
try:
# Create SSL context and connect
context = ssl.create_default_context()
with socket.create_connection((hostname, port), timeout=10) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
# Get certificate in DER format
der_cert = ssock.getpeercert(binary_form=True)
# Parse certificate using cryptography library
cert = x509.load_der_x509_certificate(der_cert, default_backend())
# Extract expiration date
expiry_date = cert.not_valid_after
days_remaining = (expiry_date - datetime.now()).days
return {
'hostname': hostname,
'expiry_date': expiry_date.strftime('%Y-%m-%d %H:%M:%S'),
'days_remaining': days_remaining,
'issuer': cert.issuer.rfc4514_string(),
'status': 'expired' if days_remaining < 0 else 'warning' if days_remaining < 30 else 'ok'
}
except Exception as e:
return {
'hostname': hostname,
'error': str(e),
'status': 'error'
}
def send_slack_alert(webhook_url, cert_info):
"""
Send formatted alert to Slack channel
"""
if cert_info['status'] in ['expired', 'warning']:
color = '#d00000' if cert_info['status'] == 'expired' else '#ff9500'
emoji = '๐จ' if cert_info['status'] == 'expired' else 'โ ๏ธ'
message = {
'attachments': [{
'color': color,
'title': f'{emoji} SSL Certificate Alert: {cert_info["hostname"]}',
'fields': [
{'title': 'Status', 'value': cert_info['status'].upper(), 'short': True},
{'title': 'Days Remaining', 'value': str(cert_info['days_remaining']), 'short': True},
{'title': 'Expiry Date', 'value': cert_info['expiry_date'], 'short': False},
{'title': 'Issuer', 'value': cert_info.get('issuer', 'Unknown'), 'short': False}
]
}]
}
requests.post(webhook_url, json=message)
# Your domains to monitor
domains = [
'example.com',
'api.example.com',
'app.example.com'
]
# Your Slack webhook URL
SLACK_WEBHOOK = 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'
# Run checks
print("๐ Starting SSL Certificate Checks...\n")
for domain in domains:
cert_info = check_ssl_expiry(domain)
if 'error' in cert_info:
print(f"โ {domain}: ERROR - {cert_info['error']}")
else:
status_emoji = 'โ
' if cert_info['status'] == 'ok' else 'โ ๏ธ' if cert_info['status'] == 'warning' else '๐จ'
print(f"{status_emoji} {domain}: {cert_info['days_remaining']} days remaining")
# Send alert if needed
send_slack_alert(SLACK_WEBHOOK, cert_info)
print("\nโ
Check complete!")
This script does four critical things:
- Actually connects to the domain via SSL handshake (not just API checks that can lie)
- Parses the certificate to get real expiration date and issuer info
- Calculates days remaining with negative numbers for expired certs
- Sends Slack alerts for anything expiring in <30 days or already expired
You can run this as a cronjob every morning:
# Add to crontab (runs daily at 8 AM)
0 8 * * * /usr/bin/python3 /path/to/ssl_check.py >> /var/log/ssl_checks.log 2>&1
The Results: Numbers Don't Lie
Six months after implementing this:
- 8 hours/week saved from manual Excel checking (416 hours/year)
- 47 certificates detected at risk of expiry before they became incidents
- 0 outages from SSL expiry (compared to 3 in the previous year)
- 15-minute setup time vs the 3 weeks I spent evaluating Datadog and New Relic
The ROI was instant. The peace of mind? Priceless.
But running a Python script from cron got old fast. What about:
- Monitoring certs from multiple servers?
- Historical tracking of certificate changes?
- Team notifications (different people for different domains)?
- Mobile alerts when I'm not at my desk?
- Dashboard to see everything at a glance?
From Script to Product
I spent the next two months turning this into something more robust. Built a proper SaaS around it. Called it NightWatch because I was tired of 2 AM wake-up calls.
The core monitoring logic is still that Python script โ because it works. But now it runs distributed checks from multiple regions, stores history in PostgreSQL, sends alerts via Slack/email/SMS, and gives me a dashboard I can actually show clients.
Full disclosure: I'm not writing this article just to share knowledge. NightWatch is a real product I charge money for. But here's the thing โ I built it because I needed it. Every feature exists because it solved a real problem I had:
- Multi-region checks: Because that one time a certificate was valid in US-East but failed in EU-West due to CDN caching
- Change detection: Because GoDaddy once issued a different cert than we requested and I didn't notice for 3 weeks
- Team notifications: Because my junior dev needed alerts for staging certs, not production
- Wildcard support: Because monitoring *.example.com manually is impossible
Free tier covers 3 domains (perfect for side projects). Pro is $7/month for 25 domains with Slack integration. Enterprise tier for teams managing hundreds.
You can keep using the Python script above โ it's solid. Open source it, fork it, make it better. But if you want the headache of scaling it removed, that's what NightWatch does.
The Question That Haunts Me
I still think about that night sometimes. The panic. The phone calls. The realization that I'd failed clients who trusted me.
But mostly I think about this: How many certificates are you monitoring right now? How many are in spreadsheets you "check regularly"? How many auto-renew... until they don't?
According to SSL Pulse, the average company has 23 public-facing SSL certificates. Most engineers I talk to can name maybe 10 of theirs off the top of their head.
The ones you forget about? Those are the ones that expire at 2:47 AM.
Try it out: If you want to see what I built, check out nightwatch.ainextstudios.com. Free tier, no credit card required. I built it to solve my problem โ maybe it solves yours too.
What's your SSL horror story? Drop it in the comments. Let's learn from each other's mistakes so we stop repeating them.
๐ Stay secure out there.
P.S. โ The Python script above is MIT licensed. Use it, modify it, sell it to your clients as value-add monitoring. Just maybe set that cronjob up before you have your own 2:47 AM moment.
Top comments (0)