step-ca-to-e-mail
Sends a weekly HTML email if step-ca certificates are expired or expiring soon.
5.4K
A tiny container that snapshots your step-ca Badger database, reads certificates via step-badger, and emails an HTML report only when there are expired or soon-to-expire certificates.
/tmp.Place your step-badger_6.5.0 binary in the build context next to the Dockerfile.
docker build -t stepca-expiry-mailer:latest .
✅ You can rename the binary; update
COPYin the Dockerfile if you do.
docker run -d --name stepca-expiry-mailer \
-e TZ="Europe/Zurich" \
-e CRON_SCHEDULE="0 6 * * 1" \
-e STEP_DB_DIR="/step/db" \
-e DB_SNAPSHOT="true" \
-e TMP_BASE="/tmp" \
-e THRESHOLD_DAYS="30" \
-e INCLUDE_EXPIRED="true" \
-e SMTP_HOST="mail-relay.local" \
-e SMTP_PORT="25" \
-e SMTP_FROM="[email protected]" \
-e SMTP_TO="[email protected],[email protected]" \
-v /path/to/step-ca/db:/step:ro \
--restart unless-stopped \
stepca-expiry-mailer:latest
docker run -d --name stepca-expiry-mailer \
-e SMTP_HOST="smtp.provider.tld" \
-e SMTP_PORT="587" \
-e SMTP_STARTTLS="true" \
-e SMTP_USERNAME="[email protected]" \
-e SMTP_PASSWORD="supersecret" \
-e SMTP_FROM="[email protected]" \
-e SMTP_TO="[email protected]" \
-v /path/to/step-ca/db:/step:ro \
--restart unless-stopped \
stepca-expiry-mailer:latest
services:
stepca-expiry-mailer:
image: stepca-expiry-mailer:latest
environment:
TZ: Europe/Zurich
CRON_SCHEDULE: "0 6 * * 1" # every Monday 06:00
STEP_DB_DIR: /step/db
DB_SNAPSHOT: "true"
TMP_BASE: "/tmp"
THRESHOLD_DAYS: "30"
INCLUDE_EXPIRED: "true"
SMTP_HOST: mail-relay.local
SMTP_PORT: "25"
SMTP_FROM: [email protected]
SMTP_TO: [email protected]
SMTP_STARTTLS: "false"
EMAIL_SUBJECT_PREFIX: "[Step-CA]"
TABLE_TITLE: "Certificates expiring soon"
volumes:
- /path/to/step-ca/db:/step:ro
restart: unless-stopped
Snapshot: The container creates a temporary copy of your Badger DB (DB_SNAPSHOT=true). This avoids the Badger directory lock.
Read: It runs step-badger x509Certs <SNAPSHOT> --emit json and parses notBefore/notAfter like the BookStack sync.
Filter: Certificates are included if:
days_left <= THRESHOLD_DAYS, orINCLUDE_EXPIRED=true.Email: If and only if there are matching entries, it sends a nicely formatted HTML email (plus a plain-text alternative).
SMTP_HOST — SMTP server hostname or IP.SMTP_FROM — sender address (e.g., [email protected]).SMTP_TO — comma-separated recipients list.CRON_SCHEDULE — cron syntax for when to run (default: 0 6 * * 1 → Monday 06:00).STEP_DB_DIR — path inside the container to your Step-CA DB root (default: /step/db).DB_SNAPSHOT — true|false (default: true) — snapshot DB into TMP_BASE before reading.TMP_BASE — base directory for snapshots (default: /tmp).THRESHOLD_DAYS — days left threshold for “soon to expire” (default: 30).INCLUDE_EXPIRED — include already expired certs (default: true).EMAIL_SUBJECT_PREFIX — subject prefix (default: [Step-CA]).TABLE_TITLE — headline shown in the email (default: Certificates expiring soon).SMTP_PORT — 25 (plain/no-auth allowed), 587 (STARTTLS), or 465 (SMTPS).SMTP_STARTTLS — true to use STARTTLS on SMTP_PORT (typically 587).SMTP_USERNAME, SMTP_PASSWORD — set when your SMTP requires auth.STEP_BADGER_CMD — default /usr/local/bin/step-badger x509CertsSTEP_BADGER_ARGS — default --emit jsonThe image assumes your
step-badgerhas thex509Certscommand. If your binary differs, adjustSTEP_BADGER_CMD/ARGS.
The container runs as root by default so it can:
/app/crontabs.Mount your Step-CA directory read-only: -v /path/to/db:/step:ro.
If you must run non-root, grant read+execute on the host to the container UID/GID (ACLs or group membership), then switch USER in the Dockerfile and keep crond -c /app/crontabs.
Permission denied / Badger lock Ensure the host path is mounted read-only and the container runs as root, or adjust host ACLs if you run non-root. Snapshotting avoids the directory lock.
“No parsable certificates with not_after”
Means step-badger JSON didn’t include notAfter fields. Make sure you’re using a compatible step-badger build with x509Certs --emit json.
No emails arrive
Check SMTP_HOST/PORT and whether your relay requires auth or STARTTLS/SMTPS. Use:
SMTP_PORT=25, SMTP_STARTTLS=false, no username/password.SMTP_PORT=587, SMTP_STARTTLS=true.SMTP_PORT=465 (no SMTP_STARTTLS), often requires auth.Cron didn’t run
Verify CRON_SCHEDULE syntax and container logs. Cron is started as crond -f -l 8 -c /app/crontabs.
MIT License – free for commercial and private use.
Content type
Image
Digest
sha256:5f8fecbc7…
Size
23.6 MB
Last updated
10 months ago
docker pull onesystems/step-ca-to-e-mail