Let's Encrypt expiry alerts with cron

Updated on September 04, 2026

Monitor Let's Encrypt expiry and get alerts with cron,
openssl, and Signalgrid.

Certificate expiries are a real headache, and they usually only show up once something has already expired and gone sideways. With this small script and Signalgrid, you get a simple Let's Encrypt expiry alert before that turns into downtime, a broken HTTPS endpoint, or an annoying production surprise.

The example keeps the Signalgrid credentials directly inside the script for quick deployment. It is mainly aimed at Let's Encrypt-backed websites, reverse proxies, and HTTPS endpoints, but it also works as a general certificate expiration monitoring and alerting script for other TLS certificates exposed on a host and port.

What this script does

  • connects to each target with openssl s_client
  • reads the expiration date from the live Let's Encrypt certificate served by the endpoint
  • sends a WARN Signalgrid notification and expiration warning when the certificate is below the warning threshold
  • sends a CRIT alert when the certificate is below the critical threshold, already expired, or the certificate could not be read

Download and install

You can download the script directly from this page and place it somewhere like /usr/local/bin.

Bash
# Download the script into /usr/local/bin curl -o /usr/local/bin/check-certificate-expiration-signalgrid.sh https://docs.signalgrid.co/downloads/check-certificate-expiration-signalgrid.sh # Make it executable chmod +x /usr/local/bin/check-certificate-expiration-signalgrid.sh # Edit the credentials and target list nano /usr/local/bin/check-certificate-expiration-signalgrid.sh

Replace the placeholder Signalgrid credentials and the example targets at the top of the file before you put it into cron or a crontab entry.

Configuration block

Setting
Description
SIGNALGRID_CLIENT_KEY
Your Signalgrid client key from the dashboard
SIGNALGRID_CHANNEL
The channel token that should receive the alert
WARNING_DAYS
How many days before expiration a warning notification or alert should be sent
CRITICAL_DAYS
How many days before expiration a critical alert should be sent
TARGETS
A Bash array of host:port pairs to check

Full source code

The downloadable script is shown below exactly as provided.

Bash
#!/usr/bin/env bash set -euo pipefail SIGNALGRID_CLIENT_KEY="your_client_key_here" SIGNALGRID_CHANNEL="your_channel_token_here" WARNING_DAYS=30 CRITICAL_DAYS=7 TARGETS=( "example.com:443" "api.example.com:443" ) push_notification() { local type="$1" local critical="$2" local title="$3" local body="$4" curl --silent --show-error --fail -X POST https://api.signalgrid.co/v1/push \ --data-urlencode "client_key=${SIGNALGRID_CLIENT_KEY}" \ --data-urlencode "channel=${SIGNALGRID_CHANNEL}" \ --data-urlencode "type=${type}" \ --data-urlencode "critical=${critical}" \ --data-urlencode "title=${title}" \ --data-urlencode "body=${body}" >/dev/null } check_target() { local target="$1" local host="${target%%:*}" local port="${target##*:}" local end_date local end_epoch local now_epoch local seconds_left local days_left end_date="$({ echo | openssl s_client -servername "$host" -connect "$host:$port" 2>/dev/null \ | openssl x509 -noout -enddate \ | cut -d= -f2 } || true)" if [ -z "$end_date" ]; then push_notification \ "CRIT" \ "true" \ "Certificate check failed: ${host}" \ "Could not read the TLS certificate from ${host}:${port}." return fi end_epoch="$(date -d "$end_date" +%s)" now_epoch="$(date +%s)" seconds_left=$((end_epoch - now_epoch)) days_left=$(((seconds_left + 86399) / 86400)) if [ "$seconds_left" -le 0 ]; then push_notification \ "CRIT" \ "true" \ "Certificate expired: ${host}" \ "${host}:${port} expired on ${end_date}." return fi if [ "$days_left" -le "$CRITICAL_DAYS" ]; then push_notification \ "CRIT" \ "true" \ "Certificate expires soon: ${host}" \ "${host}:${port} expires in ${days_left} day(s) on ${end_date}." elif [ "$days_left" -le "$WARNING_DAYS" ]; then push_notification \ "WARN" \ "false" \ "Certificate expiration warning: ${host}" \ "${host}:${port} expires in ${days_left} day(s) on ${end_date}." fi } for target in "${TARGETS[@]}"; do check_target "$target" done

Cron job example

Run the script once every morning. If a Let's Encrypt certificate is below your threshold, the script sends a notification and expiry alert. If it is still healthy, it stays quiet.

Cron
17 8 * * * /usr/local/bin/check-certificate-expiration-signalgrid.sh

Notes

  • The script checks the certificate that is actually served by the remote host, which is usually more useful for Let's Encrypt setups than checking a local certificate file.
  • This works well even if you already use Certbot for automatic Let's Encrypt renewals, because it monitors the live certificate that users actually hit.
  • The -servername option is important for SNI, especially when multiple certificates are hosted on the same IP.
  • This example uses date -d, so it is aimed at typical Linux cron environments with GNU date.