PRACTITIONER GUIDE
Practitioner Guide11 min read

TLS Certificate Expiry Automation: Stop Production Outages Before They Happen

90 days
maximum lifetime for Let's Encrypt certificates, intentionally short to force automation and discourage manual renewal workflows
30 / 14 / 7
day expiry alert thresholds used by mature certificate programs: tracking, escalation, and emergency response tiers respectively
< 60 sec
time to issue an emergency replacement certificate via certbot standalone mode when port 80 is available on the affected server
2/3 lifetime
renewal trigger point used by cert-manager in Kubernetes, initiating renewal well before expiry to allow for retry on failure

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

TLS certificate expiry is one of the few security-adjacent problems where the solution is entirely technical and requires no user behavior change. The only reliable way to prevent certificate expiry outages is automation — manual renewal processes, calendar reminders, and even dedicated team members who own certificate management all fail because humans are unreliable over multi-year timeframes and organizations change.

The Let's Encrypt ACME protocol and cert-manager for Kubernetes have made automated certificate renewal accessible for free at any scale. The gap between these tools existing and most organizations using them is implementation effort. This guide reduces that effort to a sequence of specific commands and configurations that work for web servers, load balancers, Kubernetes clusters, and internal services.

Automation architecture by deployment type

The right automation tool depends on where your certificates live and how your infrastructure is deployed. Web servers running certbot need a systemd timer and a post-renewal reload hook so the new certificate is actually served after renewal. Kubernetes workloads need cert-manager with a ClusterIssuer pointing at Let's Encrypt or a private ACME CA. Cloud load balancers running ACM, GCP Certificate Manager, or Azure Managed Certificates need nothing beyond initial provisioning because the cloud provider handles renewal entirely. Each deployment type is covered below with the specific commands and configuration required to reach zero manual steps in the renewal path.

Web servers: certbot with systemd timer and renewal hooks

Install certbot with the appropriate plugin for your web server. For nginx on Ubuntu/Debian: apt install certbot python3-certbot-nginx. Issue the initial certificate: sudo certbot --nginx -d yourdomain.com. Certbot installs a systemd timer (certbot.timer) that runs twice daily and renews any certificate within 30 days of expiry. The critical addition is a renewal hook: /etc/letsencrypt/renewal-hooks/post/reload.sh that runs nginx -s reload after each renewal. Without this hook: the certificate file is renewed but the old certificate remains in memory until the web server is restarted — causing a confusing state where the file shows a new expiry but HTTPS connections still show the old expiry. Test the full automation: certbot renew --dry-run followed by checking that the hook would be executed.

Cloud load balancers: use the cloud provider's managed certificate service

AWS Certificate Manager (ACM), GCP Certificate Manager, and Azure App Service Managed Certificates all provide fully managed TLS certificates for cloud load balancers with automated renewal. ACM certificates attached to Application Load Balancers, CloudFront distributions, or API Gateway never expire — AWS renews them automatically and you have no certificate management responsibility. Import your own certificates only when: you need client certificate (mTLS) validation, your regulatory requirements specify a particular CA, or you need to use the same certificate across cloud providers. For new deployments on cloud load balancers: use managed certificates exclusively and eliminate ACM certificate management from your operations responsibilities entirely.

Certificate inventory and monitoring

Automation prevents known certificate expirations. The certificates that cause outages are typically the ones nobody knew existed: forgotten subdomains provisioned years ago, shadow IT deployments with certificates issued under personal accounts, and internal services that were supposed to be temporary. Certificate Transparency logs are a free, public record of every certificate ever issued for your domains and are the fastest way to find these unknowns. Once you have a complete inventory, Prometheus blackbox exporter alerts give you an early warning system that fires before any certificate reaches its expiry window.

Build the inventory before expiry finds gaps for you

Use crt.sh to find every certificate issued for your domains: curl 'https://crt.sh/?q=%.yourdomain.com&output=json' | jq '[.[] | {name_value, not_after}] | sort_by(.not_after)' shows all certificates, sorted by expiry date, including expired ones. This reveals: forgotten subdomains that have active certificates, certificates issued by unexpected CAs (shadow IT or account compromise), and certificates with unusually long lifetimes (should be reviewed for compliance with your policy). For each certificate in the CT log inventory that is not in your automated renewal system: add it immediately, or determine that the subdomain is no longer in use and can be decommissioned.

Configure Prometheus blackbox exporter for expiry monitoring

The Prometheus blackbox exporter probes external endpoints and exposes TLS certificate metadata including expiry dates. Configure probe targets in blackbox.yml for every domain you own. Add a Prometheus alert rule: alert: CertExpiresIn30Days, expr: probe_ssl_earliest_cert_expiry{job="ssl-check"} - time() < 86400 * 30, for: 1h, labels: severity: warning. Add a second rule for 7-day expiry: severity: critical. Route the critical alert to PagerDuty for immediate escalation. Route the 30-day warning to a Slack channel for tracking. This alert should never fire in a fully automated environment — if it fires, the automated renewal system has failed and manual intervention is required before the service goes down.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

The bottom line

Certificate expiry outages are a failure of process, not technology — the automation to prevent them has existed for years. The correct target state is: every certificate renewed by an automated system with no human action required, monitored by alerts that fire if automation fails before expiry is reached. Achieve it with: certbot for web servers (with renewal hooks), cert-manager for Kubernetes, managed certificates for cloud load balancers, and DNS-01 ACME or a private ACME CA for internal services. Build a certificate inventory from CT log searches and network scans to find certificates that automation has not yet reached. If a 30-day expiry alert fires, it means your automation failed — investigate why before the 7-day critical alert fires and an outage becomes your next context for prioritizing this project.

Frequently asked questions

How do I set up automatic TLS certificate renewal with Let's Encrypt and Certbot?

Install certbot on your server: apt install certbot python3-certbot-nginx (for nginx) or python3-certbot-apache (for Apache). Obtain and install the first certificate: certbot --nginx -d yourdomain.com -d www.yourdomain.com. Certbot automatically modifies your nginx configuration to use the certificate and sets up a systemd timer for automated renewal. Verify renewal automation: certbot renew --dry-run should complete without error. Configure a renew-hook to reload the web server after renewal: create /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh containing #!/bin/bash nginx -s reload with chmod +x. The hook runs after every successful renewal, ensuring the new certificate is actually used by the web server. Verify the systemd timer is active: systemctl status certbot.timer should show the next renewal check scheduled.

How does cert-manager handle TLS certificate automation in Kubernetes?

cert-manager is a Kubernetes operator that automates certificate lifecycle management. Installation: helm repo add jetstack https://charts.jetstack.io; helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true. Configure a ClusterIssuer for Let's Encrypt: create a ClusterIssuer resource with type: acme, server: https://acme-v02.api.letsencrypt.org/directory, and solvers using either HTTP-01 (requires public HTTP access on port 80) or DNS-01 (requires API access to your DNS provider, works for internal or wildcard certs). Create Certificate resources or add cert-manager annotations to Ingress objects (cert-manager.io/cluster-issuer: letsencrypt-prod, and a tls block with secretName). cert-manager monitors certificate expiry and renews automatically at 2/3 of the certificate's lifetime.

How do I build a certificate inventory to find every TLS certificate in our environment?

Certificate inventory discovery methods: (1) Network scan with sslyze or nmap SSL scripts: nmap -sV --script ssl-cert -p 443,8443 10.0.0.0/16 scans all hosts in a subnet and extracts certificate subject, issuer, and expiry. (2) Certificate Transparency log search: search crt.sh for your domains (crt.sh?q=%.yourdomain.com) to find every publicly-trusted certificate ever issued for your domain — includes forgotten subdomains and shadow IT deployments. (3) DNS zone walk: enumerate all DNS records for your domains and test each A/AAAA record for TLS — many certificate expirations happen on subdomains that were set up years ago and forgotten. (4) Cloud provider inventory: AWS Certificate Manager, GCP Certificate Manager, and Azure Key Vault all have API endpoints to list managed certificates — pull these to add to your inventory. Combine all sources into a single inventory sheet with domain, expiry date, owner, and renewal method.

What should I do when a production TLS certificate expires and I cannot renew it automatically?

Emergency expired certificate response: (1) Issue a temporary certificate immediately using certbot or your CA's emergency process — for Let's Encrypt, certbot certonly --standalone -d yourdomain.com on a server with port 80 available issues a new certificate in under 60 seconds. (2) If you cannot use ACME (internal CA, no internet access): request an emergency certificate from your internal CA using your existing CSR process, or use a self-signed certificate temporarily while you complete the proper renewal (communicate to users that they may see a certificate warning briefly). (3) Deploy the new certificate: update the certificate path in your web server configuration or load balancer and reload the service. (4) Post-incident: add this certificate to your monitoring system and implement automated renewal before the next expiry. An expired certificate is never an acceptable production state — a 60-second emergency renewal via certbot should be in every operations runbook.

How do I monitor TLS certificate expiry across all my domains and servers?

Monitoring options by complexity: (1) Simple bash script: openssl s_client -connect yourdomain.com:443 </dev/null 2>/dev/null | openssl x509 -noout -enddate gives the expiry date — add to cron and send alerts 30 days before expiry. (2) Prometheus/Grafana: use the blackbox exporter with probe_ssl_earliest_cert_expiry metric to track expiry dates for all configured endpoints. Alert rule: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 triggers at 30 days. (3) Dedicated certificate monitoring services: Datadog, New Relic, and specialized tools like Cert Spotter, CertAlert, and Uptime Robot provide certificate expiry monitoring with configurable thresholds and multi-channel alerting. (4) For wildcard certs and internal services: monitor the cert file modification time on disk alongside the expiry date — some automation renews the file but does not reload the service.

How does ACME DNS-01 challenge work and when should I use it instead of HTTP-01?

ACME HTTP-01 validates domain control by serving a file on port 80 of the domain — requires that the server running certbot is publicly accessible on port 80. ACME DNS-01 validates domain control by creating a temporary DNS TXT record (_acme-challenge.yourdomain.com) — works for servers without public internet access (internal servers, VMs behind NAT) and is required for wildcard certificates (* .yourdomain.com). Use DNS-01 when: the server cannot expose port 80 to Let's Encrypt's validation servers, you need a wildcard certificate, or you are issuing certificates for internal DNS names. Automate DNS-01 by granting certbot API access to your DNS provider (certbot has plugins for Route53, Cloudflare, Namecheap, and others) — fully automated DNS-01 renewal requires no manual DNS record management.

How do I handle TLS certificate automation for internal services that cannot use Let's Encrypt?

For internal services (private DNS names, services unreachable from the internet): options include (1) Private CA with ACME: set up step-ca (open source) or HashiCorp Vault PKI Secrets Engine as an internal ACME-compatible CA — cert-manager and certbot can use these as issuers just like Let's Encrypt, enabling full automation for internal certificates. (2) Short-lived certificates from Vault PKI: issue certificates with 30-day lifetimes from Vault PKI and configure cert-manager or your application to renew at 15 days — short lifetimes with automated renewal eliminate the expiry risk without requiring ACME. (3) Wildcard certificate from a public CA: if internal services use subdomains of a public domain (internal.yourdomain.com), a wildcard certificate from Let's Encrypt via DNS-01 covers internal services without exposing them to the internet. The goal in all cases is automation — any certificate with a manual renewal step will eventually expire because of the human reliability gap.

Sources & references

  1. Let's Encrypt Documentation
  2. cert-manager Kubernetes Documentation
  3. ACME Protocol (RFC 8555)
  4. Mozilla Certificate Expiry Monitoring

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.