#!/usr/bin/env python3 import subprocess from datetime import datetime, timezone from pathlib import Path CERT_ROOT = Path( "/opt/docker/caddy/data/caddy/certificates/" "acme-v02.api.letsencrypt.org-directory" ) def collect(): certificates = [] for cert_file in sorted(CERT_ROOT.glob("*/*.crt")): result = subprocess.run( ["openssl", "x509", "-in", str(cert_file), "-noout", "-enddate"], capture_output=True, text=True, ) if result.returncode != 0: continue expires_text = result.stdout.strip().removeprefix("notAfter=") expires = datetime.strptime( expires_text, "%b %d %H:%M:%S %Y %Z", ).replace(tzinfo=timezone.utc) days_remaining = (expires - datetime.now(timezone.utc)).days certificates.append({ "name": cert_file.parent.name, "days_remaining": days_remaining, "expires": expires.isoformat(), }) if not certificates: return { "state": "offline", "summary": "No certificates", "detail": "Caddy certificate files not found", } lowest = min(item["days_remaining"] for item in certificates) state = "online" if lowest < 30: state = "warning" if lowest < 7: state = "offline" return { "state": state, "summary": f"{len(certificates)} certificates", "detail": f"{lowest} days minimum", "minimum_days": lowest, "certificates": certificates, }