Why monitor SSL expiry
Let's Encrypt auto-renewal is great until it silently fails. A DNS change, a firewall rule, or a misconfigured Certbot hook — and your cert expires without warning. Browsers show scary "Not Secure" banners, APIs start rejecting TLS, and users leave.
Single domain check
#!/bin/bash
# /usr/local/bin/nerve-ssl-check.sh
export NERVE_DSN="nerve://TOKEN:[email protected]"
DOMAIN="example.com"
WARN_DAYS=14
EXPIRY=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "$EXPIRY" ]; then
echo "SSL CHECK FAILED: cannot reach $DOMAIN" | nerve send --severity critical
exit 1
fi
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s 2>/dev/null || date -jf "%b %d %T %Y %Z" "$EXPIRY" +%s 2>/dev/null)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -le 0 ]; then
echo "SSL EXPIRED: $DOMAIN (expired ${DAYS_LEFT#-} days ago)" | nerve send --severity critical
elif [ "$DAYS_LEFT" -le "$WARN_DAYS" ]; then
echo "SSL EXPIRING: $DOMAIN in $DAYS_LEFT days" | nerve send --severity alert
fi
# Run daily at 8 AM
0 8 * * * /usr/local/bin/nerve-ssl-check.sh
Multiple domains
#!/bin/bash
export NERVE_DSN="nerve://TOKEN:[email protected]"
WARN_DAYS=14
DOMAINS=(
"example.com"
"api.example.com"
"dashboard.example.com"
"staging.example.com"
)
for DOMAIN in "${DOMAINS[@]}"; do
EXPIRY=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "$EXPIRY" ]; then
echo "SSL UNREACHABLE: $DOMAIN" | nerve send --severity critical
continue
fi
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s 2>/dev/null || date -jf "%b %d %T %Y %Z" "$EXPIRY" +%s 2>/dev/null)
DAYS_LEFT=$(( (EXPIRY_EPOCH - $(date +%s)) / 86400 ))
if [ "$DAYS_LEFT" -le 0 ]; then
echo "SSL EXPIRED: $DOMAIN" | nerve send --severity critical
elif [ "$DAYS_LEFT" -le "$WARN_DAYS" ]; then
echo "SSL EXPIRING: $DOMAIN in $DAYS_LEFT days" | nerve send --severity alert
fi
done
After Certbot renewal
Add a deploy hook to notify you when renewal succeeds (or fails).
# /etc/letsencrypt/renewal-hooks/deploy/nerve-notify.sh
#!/bin/bash
export NERVE_DSN="nerve://TOKEN:[email protected]"
echo "SSL renewed: $RENEWED_DOMAINS on $(hostname)" | nerve send
chmod +x /etc/letsencrypt/renewal-hooks/deploy/nerve-notify.sh
GitHub Actions: scheduled SSL check
name: SSL Expiry Check
on:
schedule:
- cron: '0 8 * * *'
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Check SSL
env:
NERVE_DSN: ${{ secrets.NERVE_DSN }}
run: |
go install github.com/nerve-ink/nerve-cli/cmd/nerve@latest
for DOMAIN in example.com api.example.com; do
DAYS=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2 \
| xargs -I{} bash -c 'echo $(( ($(date -d "{}" +%s) - $(date +%s)) / 86400 ))')
if [ "$DAYS" -le 14 ]; then
echo "SSL EXPIRING: $DOMAIN in $DAYS days" | nerve send --severity alert
fi
done
Quick start
go install github.com/nerve-ink/nerve-cli/cmd/nerve@latest
export NERVE_DSN="nerve://TOKEN:[email protected]"
echo "SSL EXPIRING: example.com in 7 days" | nerve send --severity alert
FAQ
How do I get notified before my SSL certificate expires?
Run a daily cron job that checks the expiry date with openssl s_client and sends a Nerve signal when it is within your threshold (e.g., 14 days).
Does this work with Let's Encrypt auto-renewal?
Yes. Even with auto-renewal, renewals can silently fail. This script catches it before the certificate actually expires.
Can I check multiple domains?
Yes. Loop over a list of domains and check each one. The script sends a separate alert for each domain close to expiry.