The number-one cause of "the site just stopped working" incidents is an expired TLS certificate that nobody noticed. The number-two cause is a renewed cert that was issued correctly but never reloaded by nginx / Apache / your load balancer.
Both are preventable with a one-time setup. This guide walks through configuring an SSL expiry monitor on Trace Warrior, picking the right thresholds, picking the right cadence, and routing the alert somewhere that will actually be seen.
What an SSL expiry monitor actually does
Once a day (by default), our worker runs the same TLS handshake the SSL Certificate Checker runs against your target. It records the daysRemaining, the issuer, the protocol, and whether the chain is complete. When daysRemaining crosses a threshold, you get an email, and on Starter plans and above, a webhook hits your Slack / Discord / PagerDuty endpoint with a signed JSON payload.
Default thresholds are warning at ≤30 days, critical at ≤7 days. You can override these per monitor.
Step 1. Open the new-monitor flow
Sign in and open /dashboard/monitors/new/ssl-expiry. Every plan includes monitoring — the Free tier covers 3 monitors with email alerts. If you're already at your plan's monitor limit, you'll be bounced back to the monitors index with an upgrade prompt; Starter at $9/month raises the limit to 15 and adds webhooks, with a 14-day free trial.
Step 2. Enter the target
The two required fields:
- Hostname - the same name your browser hits.
api.example.com, nothttps://api.example.com. Use the hostname users actually visit, not just the apex domain. A cert valid forexample.commight not coverwww.example.com(or vice versa). - Port - defaults to 443. Other ports you might monitor:
- 465 - SMTPS (legacy)
- 993 - IMAPS
- 636 - LDAPS
- 8443 - HTTPS on an alt port
For STARTTLS-style protocols (SMTP submission on 587, IMAP on 143), the SSL monitor's direct TLS handshake won't work. Those start in plaintext and upgrade. Monitor the direct-TLS variants instead.
Step 3. Pick the thresholds
The defaults, 30 days warning, 7 days critical, are calibrated for the most common cert lifecycle: 90-day Let's Encrypt certificates renewed on a 60-day cron.
Adjust them based on your renewal cadence:
| Renewal cadence | Warning | Critical | Why |
|---|---|---|---|
| Automated, 60-day cron (Let's Encrypt + certbot) | 30 days | 7 days | If you're at 30 days with no renewal, the cron is broken |
| Automated, managed (Cloudflare, Vercel, AWS ACM) | 14 days | 3 days | Renewal is fully managed; an alert means something's genuinely wrong |
| Manual annual (DigiCert, Sectigo, internal CA) | 60 days | 30 days | You need lead time to procure + install |
Be honest about whose hands the renewal is in. If it's a human's responsibility, give them lead time.
Step 4. Pick the check interval
Default: daily. That's almost always right. SSL certs don't change on the minute, and a 24-hour gap between checks means the worst-case time-to-alert is 24 hours, still useful when your warning window is 30 days.
If you want sub-daily checks (every plan supports them — down to 10 minutes on Free, 5 on Starter, 1 minute on Professional and Enterprise), you can, but you're paying for it in monitor capacity. We'd recommend keeping SSL on daily and using the minute-level cadence on port and HTTP monitors instead.
Step 5. Pick the alert channels
Email is on by default. It routes to the email address on your Trace Warrior account, sent from alerts@tracewarrior.com. Subject line is [Trace Warrior · CRITICAL] <monitor name> - <summary> so it's filter-friendly.
Webhook is available on Starter and above. Drop in a URL and we'll POST a JSON payload signed with an HMAC-SHA256 secret (revealed once on creation. Save it). Common targets:
- Slack - use a Slack Incoming Webhook URL directly, or send to a thin proxy that reshapes the payload into Slack Block Kit
- Discord - Discord webhooks accept any JSON body via the proxy pattern
- PagerDuty - point at a Events API v2 endpoint with the right routing key in your proxy
- Your own listener - verify the
X-TraceWarrior-Signatureheader before trusting the payload
The webhook payload looks like:
{ "event": "monitor.fired", "severity": "critical", "monitor": { "id": "...", "name": "...", "target": "api.example.com:443" }, "check": { "state": "critical", "result": { "daysRemaining": 6 } }, "previous_state": "ok" }
A monitor.recovered event fires when the cert is renewed and the next check returns OK.
Step 6. Save and verify
Click Create monitor. If you set a webhook URL, a one-time secret reveal modal appears. Copy that secret somewhere safe; we don't show it again.
The first check runs immediately and you'll see a state pill: pending → first check → ok (or warning / critical if the cert is actually already in your alert window). The detail page shows the full check result, issuer, valid dates, SAN list, protocol, cipher.
Test the alerting path before you need it. Two ways:
- Run a known-broken target. Create a second SSL monitor against
expired.badssl.com:443. The first check will fire a critical alert. Confirm the email + webhook landed. Delete the test monitor. - Lower the threshold temporarily. Set warning days to a value above the cert's current daysRemaining. The next check transitions ok → warning and fires the alert. Restore the threshold.
If neither alert arrives, check that you saved your webhook secret correctly and that the email address on your account is reachable (no typos, not in spam).
Common SSL-monitoring mistakes
Monitoring the apex when users visit www. If your site uses www.example.com but you monitor example.com, you may be watching the apex-redirect cert (often Let's Encrypt) instead of the canonical site cert (often Cloudflare-managed). Always monitor the hostname users actually hit.
Setting warning days too low. If your renewal is manual annual and warning is set at 7 days, you won't have time to procure and install. Match the threshold to the human lead time, not the cert's technical TTL.
Monitoring only port 443 when you also run mail. SMTPS on 465, IMAPS on 993, and submission on 587 all have separate certs (often, anyway). Bounced mail because the SMTPS cert expired is a different incident from a broken website.
Ignoring the chain. The SSL monitor flags chainComplete: false in its result. If your server only serves the leaf cert (not the intermediates), modern browsers paper over it but older Java clients, IoT devices, and curl from old base images will break. Look at the result; don't just trust the state pill.
Not testing the alert path. A monitor that never alerts because the webhook signature is wrong or the email is in spam is worse than no monitor. False confidence. Fire a test alert deliberately on day one.
TL;DR
- Open /dashboard/monitors/new/ssl-expiry.
- Enter the hostname users actually visit + the port (443 for HTTPS).
- Set thresholds based on your renewal lead time. Default 30/7 is right for Let's Encrypt.
- Daily cadence is right for SSL.
- Enable email + (optionally) a webhook for Slack / Discord / PagerDuty.
- Save → first check runs immediately.
- Test the alert path on day one against a known-broken target.
Recovery alerts fire automatically when the cert renews and the next check returns OK, so you'll know the rollout landed.
Related
- How to verify an SSL certificate - the one-shot version of this workflow
- SSL Certificate Checker tool - what the monitor wraps
- How to monitor DNS records for drift - the same pattern, different tool
