A POSIX-compliant shell script designed to monitor Let's Encrypt (or any X.509) certificate expiration.
Specifically built to handle the limited date command functionality found in BusyBox/Alpine environments.
- Nagios/Zabbix Compatible: Returns standard exit codes (0, 1, 2, 3).
- Lightweight: No heavy dependencies; requires only
opensslandawk. - Docker-Ready: Perfect for health checks or sidecar monitoring containers.
The script follows a tiered alerting strategy optimized for 90-day (Let's Encrypt) lifecycles.
| Exit Code | Status | Threshold | Description |
|---|---|---|---|
| 0 | OK | > 30 Days | Certificate is healthy. |
| 0 | NOTICE | 8 - 30 Days | Near-term expiry; check renewal logs. |
| 1 | WARNING | 0 - 7 Days | Action required. Renewal is failing or delayed. |
| 2 | CRITICAL | < 0 Days | Certificate Expired. Service is impacted. |
| 3 | UNKNOWN | N/A | Script/OpenSSL error or missing files. |
[OK] example.com: 89 days remaining (2026-03-29 22:36:20 MST)
[NOTICE] api.example.com: 16 days remaining (2026-01-15 14:10:05 MST)
[WARNING] dev.example.com: 1 day remaining (2025-12-31 09:00:00 MST)
This script is designed to run inside a container to monitor certificates mounted from the host (e.g., from a Certbot volume).
# Build the image
docker build -t cert-monitor .
# Run the check with local timezone support and read-only volume
docker run --rm \
-e TZ=America/Phoenix \
-v /etc/letsencrypt:/etc/letsencrypt:ro \
cert-monitor example.comNote: This script runs once and exits. To run this as a persistent service in Docker, ensure your script includes a
sleeploop, is managed by a scheduler like Cron, or is called by a wrapper script as needed.
Pro Tip: Using the
:roflag ensures the monitoring script cannot accidentally modify your live certificates. Setting theTZvariable ensures the log timestamps match your host system.