Host your own email and enhance your privacy
Fired by:
BlackboxTLSCertExpiringSoonWarning (<21 days) and BlackboxTLSCertExpiringSoonCritical (<7 days) — sourced from probe_ssl_earliest_cert_expiry on the live TLS handshake against each endpoint the blackbox-tls scrape job targets.The alert’s instance label identifies which endpoint is expiring. Two distinct certs live behind two distinct endpoints:
instance |
Cert | Termination point | Renewal path |
|---|---|---|---|
https://<control-domain>/ |
ACM *.<control-domain> (wildcard) |
CloudFront | AWS auto-renewal (DNS validation) |
smtp-out.<control-domain>:465 |
Let’s Encrypt (per-host) | smtp-out container | cabal-certbot-renewal Lambda |
imap.cabal.internal:143 |
Let’s Encrypt (per-host) | imap container (STARTTLS) | cabal-certbot-renewal Lambda |
(The ACM row used to read imap.<control-domain>:993. That NLB listener was removed; CloudFront fronts the same wildcard cert, so the ACM signal moved to the blackbox-http probe. The imap row is new for the same reason: the tier now terminates its own TLS on 143+STARTTLS with the Let’s Encrypt cert, the same material smtp-out serves.)
(There used to be a parallel pair of CertExpiringSoon{Warning,Critical} rules sourced from aws_certificatemanager_days_to_expiry_minimum. cloudwatch_exporter v0.16.0 silently dropped that metric under every configuration we tried; the blackbox path measures the same cert from a more honest place — what’s actually on the wire — so the CloudWatch source was removed. The runbook below covers both renewal pipelines because either alert can fire from a different cause.)
The TLS certificate serving `` is approaching expiry. ACM normally auto-renews around T-30; the certbot Lambda runs daily and renews once half the certificate’s lifetime has passed. <21 days remaining on either source means that pipeline is stuck.
When a cert actually expires:
TF_VAR_MAIL_DOMAINS have no certs by design (they are address namespaces only) — only the control domain has one.:465/:587/imap :143) — SMTP submission to smtp-out fails TLS handshake. Outbound delivery via port 25 to peer MXes continues since most peers don’t validate, but customer-side submission stops. The imap tier serves the same cert on 143, and the API Lambdas verify it on every STARTTLS, so mailbox access fails too.Which pipeline depends on which endpoint the alert names.
instance is the control-domain HTTPS probe (ACM cert)aws acm describe-certificate --certificate-arn <arn> \
--query 'Certificate.{status:Status,renewalStatus:RenewalSummary.RenewalStatus,reason:RenewalSummary.RenewalStatusReason,validations:RenewalSummary.DomainValidationOptions}'
RenewalStatusReason usually identifies the issue (DOMAIN_NOT_ALLOWED_BY_CAA, DOMAIN_VALIDATION_DENIED, missing CNAME, etc.).
_<random>.<control-domain> records in the public hosted zone against the ResourceRecord entries from step 1. Re-add any that are missing.Certificate.Arn. A mismatch means the listener is pinned to an old ARN.instance ends in :465 or :587 (Let’s Encrypt cert)cabal-certbot-renewal last run? Check the Lambda’s last invocation and any errors:
aws lambda invoke --function-name cabal-certbot-renewal /tmp/out.json && cat /tmp/out.json
# renew even though it reports "not due":
aws lambda invoke --function-name cabal-certbot-renewal --cli-binary-format raw-in-base64-out --payload '{"force": true}' /tmp/out.json
aws logs tail /aws/lambda/cabal-certbot-renewal --since 7d
The Lambda is scheduled and also can be invoked manually to force a renewal attempt.
aws ecs update-service --cluster cabal-mail --service cabal-smtp-out --force-new-deployment
429 or rateLimited responses; if hit, wait until the window clears before re-running.If ACM renewal is stuck and the cert has <14 days remaining:
aws acm request-certificate --domain-name '*.<control-domain>' --validation-method DNS. This issues a new ARN; you’ll need to update everywhere it’s referenced (CloudFront, ALB listeners, NLB listener). Don’t do this lightly — it’s destructive to live traffic during the cutover.If the Let’s Encrypt renewal is stuck and the cert has <7 days remaining:
certbot certonly --manual from a workstation with the validation TXT records published, then upload the resulting PEM bundle to wherever cabal-certbot-renewal writes its output (SSM Parameter Store under /cabal/letsencrypt/*), then force a smtp-out redeploy.