Recued
Menu
← Back to recipes

Check the certificates

by recued-core v2 8 views

Use “Check the certificates” in Recued. Read every registered certificate and record whether it is healthy, running out within thirty days, or unreadable. A file that cannot be parsed is reported as unreadable rather than counted as healthy, because those two answers look identical to the expiry check on its own.

Complete workflow

Certificate Watch 4 pinned recipes

Use Certificate Watch in Recued for tls, expiry, monitoring, and openssl. It includes 6 built-in actions and 3 ready-to-run workflows. Actions that change data use Recued's approval controls.

You are viewing one recipe in this workflow. Installing it opens the complete pack so its other recipes and background automations arrive together.

Use “Check the certificates” in Recued. Read every registered certificate and record whether it is healthy, running out within thirty days, or unreadable. A file that cannot be parsed is reported as unreadable rather than counted as healthy, because those two answers look identical to the expiry check on its own.

pack:certificate-watchcertificatetlsexpiry
by recued-core pinned v2

Use “Register a certificate to watch” in Recued. Record one certificate file so Check the certificates will read it. Keyed on its path, so re-registering the same file converges.

pack:certificate-watchcertificatetlsrecords
by recued-core pinned v2

Use “Show the certificates” in Recued. List watched certificates with their status, subject and expiry. Read-only — it re-reads no file and re-runs no check.

pack:certificate-watchcertificateboardrecords
by recued-core pinned v2
View pack details, dependencies, and permissions →

Why each certificate is probed twice

⛔⛔ A FAILING check is the ALERT here, not an error — and that is what makes it ambiguous. cert.not_expiring_30d runs openssl x509 -checkend 2592000, which exits 0 when the certificate survives the next thirty days and non-zero when it does not. Measured live on 2026-07-30:

filecert.subject_readcert.not_expiring_30d
:--:--:--
valid 365 days00
valid 9 days01
not a certificate at all11

So the expiry check cannot tell "expires in nine days" from "this file is not a certificate" — both are exit 1. A watcher that read only that would report a corrupt path as an urgent renewal, and — far worse — would look identical whether it was watching a real certificate or a typo.

⇒ Every file gets a cert.subject_read probe as well. It succeeds on anything parseable and fails on anything else, which separates the three outcomes cleanly: readable ∧ ¬expiring is healthy, readable ∧ expiring is the alert, and ¬readable is unreadable and never counted as healthy.

The foreach is what makes this safe. A foreach step collects per-item failures as {ok:false} and still returns normally, so an expiring certificate — which IS a failing step — cannot end the run before the others are checked. That is also why these checks are not prefetch steps: the list of certificates is itself a step result, and prefetch runs in parallel and cannot read one.

Thirty days is fixed by the operation, not chosen here. cert.not_expiring_30d hard-codes -checkend 2592000; there is no shorter or longer horizon available, so this recipe cannot offer one. A different window needs a new operation in the openssl-x509 pack.

This reads certificate FILES on disk. There is no operation in the pack that fetches a certificate from a live host, so this watches the files your server already has — an ACME-issued chain, a bundle you were sent — not a remote endpoint's live certificate. Those are different claims and this makes the weaker one.

expiring includes ALREADY EXPIRED. -checkend answers one question — "will it still be valid then" — and a certificate that lapsed last month fails it exactly as one lapsing next week does. Read Expires for which it is.

How it works 34 steps

Inspect the data fetches, transforms, gates, and output this recipe runs.

Process (34 steps)
registered ?
all_rows default
Apply default
all_rows_sorted sort
Sort by label
registered_count count
Count items in all rows sorted
rows slice
Take a subset of
checked_count count
Count items in rows
skipped_count math
Calculate registered count minus checked count
paths pluck
Extract path from each item
readable_probe ?
expiry_probe ?
dates_probe ?
readable_rows map
Extract from each item
expiry_rows map
Extract from each item
dates_rows map
Extract from each item
with_expiry enrich_by
Apply enrich_by
with_dates enrich_by
Apply enrich_by
joined enrich_by
Apply enrich_by
unreadable_rows filter
Filter by condition
readable_only filter
Filter by condition
healthy_rows filter
Filter by condition
expiring_rows filter
Filter by condition
healthy_count count
Count items in healthy rows
expiring_count count
Count items in expiring rows
unreadable_count count
Count items in unreadable rows
trustworthy compare
Check if unreadable count equals 0
caveat ternary
Apply ternary
checked_at date_add
Add 0 seconds to
healthy_writes map
Extract from each item
expiring_writes map
Extract from each item
unreadable_writes map
Extract from each item
all_writes flatten
Flatten nested lists in
apply_writes ?
written_count count
Count items in all writes
card to_summary
Format results as a summary card
Settings 1 configurable

Configurable at install. Defaults shown — change them anytime in Recued.

limit setting = 50

About

Tags

pack:certificate-watchcertificatetlsexpiryopensslrecordsv2

Details

34 steps 1 configurable settings recipe_id: check-certificates