ForEach icon
Request icon
Get icon
Script icon
If icon
SlackIncomingWebhook icon
MailSend icon
Set icon
Schedule icon

Monitor SSL Certificate Expiry and Alert via Slack and Email Before They Expire

Monitor SSL certificate expiry across multiple domains with Kestra. Checks days remaining, tracks alert state in the KV store, and notifies Slack and email.

Categories
Infrastructure

Catch expiring SSL certificates before browsers do. This blueprint runs a weekly SSL certificate expiry monitor across a configurable list of domains, computes the days remaining until expiration with Python, and fires Slack and email alerts when a certificate crosses your warning threshold. A KV store entry prevents duplicate notifications on every run until the certificate is renewed, so on-call channels stay quiet between real events.

How it works

  1. A io.kestra.plugin.core.trigger.Schedule trigger fires every Monday at 09:00 UTC (cron: "0 9 * * 1").
  2. io.kestra.plugin.core.flow.ForEach iterates over the domains input with concurrencyLimit: 5, checking up to five certificates in parallel.
  3. For each domain, io.kestra.plugin.core.http.Request calls the public ssl-checker.io API to retrieve cert_exp_date and cert_valid.
  4. io.kestra.plugin.core.kv.Get reads the per-domain alert state key (ssl_alerted_<domain>) with errorOnMissing: false.
  5. io.kestra.plugin.scripts.python.Script parses the expiry timestamp, computes days_left, and sets is_expiring when the cert is below the warning threshold or already invalid.
  6. io.kestra.plugin.core.flow.If gates alerting on is_expiring AND the KV state not equal to alerted.
  7. When triggered, io.kestra.plugin.slack.notifications.SlackIncomingWebhook posts a warning to Slack and io.kestra.plugin.email.MailSend sends an HTML email via SMTP on port 465.
  8. io.kestra.plugin.core.kv.Set writes alerted to the KV key so the same certificate does not re-alert on the next weekly run.

What you get

  • Parallel SSL checks across many domains with a single declarative flow.
  • Configurable warning_days threshold (default 30) plus detection of already-invalid certificates.
  • Deduplicated alerts via Kestra KV state, one notification per certificate per renewal cycle.
  • Slack message and HTML email with the domain, days remaining, and expiry date.
  • Weekly cron coverage with no servers to maintain.

Who it's for

  • DevOps, SRE, and platform teams owning certificate lifecycle across many domains.
  • Security teams that need auditable, proactive expiry coverage.
  • SaaS companies avoiding outages and browser warnings from forgotten renewals.
  • Agencies managing SSL for multiple client websites.
  • Teams replacing paid monitors (SSL Shopper, Pingdom certificate checks) with a self-hosted pipeline.

Why orchestrate this with Kestra

ssl-checker.io is a stateless API, it cannot remember which domains you already alerted on, batch them, throttle to a daily window, or notify multiple channels at once. Kestra adds the missing layer: a scheduled trigger, a ForEach with bounded concurrency, retries on transient HTTP failures, KV state to suppress duplicate alerts, declarative YAML versioned in Git, and full execution lineage per domain. Replace the schedule with a webhook or event trigger and the same flow becomes on-demand. Swap Slack for Teams, PagerDuty, or Opsgenie without rewriting the check logic.

Prerequisites

  • A Kestra instance with the plugin-scripts-python, plugin-notifications (Slack), and plugin-email plugins available.
  • A Slack Incoming Webhook URL.
  • SMTP credentials for outbound email (host, username, password, sender, recipient).

Secrets

Configure these secrets in your Kestra instance or namespace:

  • SLACK_WEBHOOK_URL, the Slack Incoming Webhook for alert messages.
  • ALERT_EMAIL_FROM, the sender address used by MailSend.
  • ALERT_EMAIL_TO, the recipient address for SSL alerts.
  • SMTP_HOST, the outbound SMTP server (SMTPS on port 465).
  • SMTP_USERNAME, the SMTP user.
  • SMTP_PASSWORD, the SMTP password.

Quick start

  1. Add the blueprint to a namespace and set the required secrets above.
  2. Edit the domains input default list, or pass domains at execution time.
  3. Adjust warning_days if 30 days is too aggressive or too lax for your renewal SLA.
  4. Trigger one manual execution to verify Slack and email both deliver.
  5. Leave the schedule enabled, the Monday 09:00 UTC run will handle the rest.

How to extend

  • Log every check (not just alerts) to a Postgres or BigQuery table for historical reporting.
  • Add an escalation branch: critical (days_left <= 7) goes to PagerDuty, normal stays in Slack.
  • Reset the KV alerted key automatically once days_left jumps back above the threshold (renewal detected).
  • Add an internal-CA branch that hits a private SSL inspection endpoint instead of ssl-checker.io.
  • Group alerts by team using domain-to-owner mapping pulled from a CMDB or YAML input.
  • Swap the weekly schedule for an event trigger that runs after every deploy.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.