sslmonitor.com hosts ssl_monitor.sh, a free Bash script from the Forward Email team that checks when your SSL/TLS certificates expire and emails you before they do.
Each run, ssl_monitor.sh:
- Reads domains from
/etc/ssl_monitor/domains.txt, one per line (#comments and empty lines are skipped). If the file is missing, it creates it with two sample domains. - Connects to each domain on port 443 with
openssl s_client(SNI set to the domain) and reads the certificate'snotAfterdate. - Marks each domain
OK,WARNING(fewer thanWARNING_DAYS, default 30, days left),CRITICAL(fewer thanCRITICAL_DAYS, default 7) orERROR(no certificate could be read). - Appends the results to
/var/log/ssl_monitor.log. - If any domain is not
OK, sends one HTML report of all domains through the Forward Email API (default) or localsendmail.
Requirements: Bash, OpenSSL, GNU date, and curl with a Forward Email API token (paid plan) or a working sendmail. It checks port 443 and expiry dates only.
sudo curl -fsSL -o /usr/local/bin/ssl_monitor.sh \
https://raw.githubusercontent.com/forwardemail/sslmonitor.com/main/ssl_monitor.sh
sudo chmod 700 /usr/local/bin/ssl_monitor.sh
sudo nano /usr/local/bin/ssl_monitor.sh # set EMAIL_TO, EMAIL_FROM, FORWARD_EMAIL_API_KEY
sudo mkdir -p /etc/ssl_monitor
echo "example.com" | sudo tee /etc/ssl_monitor/domains.txt
sudo /usr/local/bin/ssl_monitor.sh && sudo tail /var/log/ssl_monitor.logThen run it daily from root's crontab (sudo crontab -e):
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 8 * * * /usr/local/bin/ssl_monitor.sh
The full guide is at sslmonitor.com/install/.
The site is static HTML served by GitHub Pages from the root of the main branch. There is no build step on GitHub: every generated file is committed.
| Path | What it is |
|---|---|
src/content/*.md |
Page content in Markdown. Edit these. |
scripts/build.js |
Page list (titles, descriptions, navigation), layout, structured data and the Markdown renderer. |
css/style.css |
The only stylesheet. The build writes the minified css/style.min.css. |
images/og.svg, images/favicon.svg |
Sources for the social image and icons. |
scripts/render-images.js |
Renders the PNG images from those SVGs with headless Chrome. |
The build generates, in the repository root:
index.htmland<slug>/index.htmlfor each page, plus404.html<slug>.md(andindex.md), a Markdown copy of each pagesitemap.xml,robots.txt,llms.txt,llms-full.txt,site.webmanifest.well-known/security.txtand.nojekyll(so GitHub Pages serves files as they are)
-
Edit the Markdown in
src/content/. The install page includes the currentssl_monitor.shthrough the{{SCRIPT}}placeholder, so it updates when the script changes. -
To add a page, add a
.mdfile and an entry toPAGESinscripts/build.js(slug, title of 50 to 60 characters, description of about 120 to 130 characters,h1, lead andllmssummary). -
Rebuild with Node 18 or later (no dependencies):
node scripts/build.js
-
Commit the source and the generated files together.
If you change images/og.svg or images/favicon.svg, render the PNGs again:
CHROME_PATH=/path/to/chrome node scripts/render-images.jsTo preview locally, serve the repository root with any static server, for example npx http-server . -p 8080.
The site uses no JavaScript, cookies, analytics or third-party requests. Keep it that way: the pages set a Content Security Policy that only allows same-origin styles and images.
.well-known/security.txt has an Expires date in scripts/build.js. Move it forward before it passes.
Open an issue or pull request for bugs and suggestions. Report security problems privately as described in the Forward Email security policy: email security@forwardemail.net.