TLS Certificate Management: Expiry, Renewal, and Automation
Prevent certificate-related outages with proper lifecycle management, automated renewal, and monitoring best practices.
A TLS certificate is not a set-and-forget asset. Certificates expire, certificate authorities revoke them, and misconfigured chains silently break trust for a subset of your users. Certificate health goes far beyond what the browser padlock indicates — every production domain needs a lifecycle management strategy that covers issuance, renewal, chain validation, and monitoring. This guide walks through each stage with concrete commands and configurations you can apply today.
Certificate Lifecycle
Every TLS certificate moves through four stages:
- Issuance -- A certificate authority (CA) validates your control over a domain and signs a certificate. For most teams, this means Let's Encrypt issuing a domain-validated (DV) certificate via the ACME protocol.
- Active use -- The certificate is installed on your web server and presented during every TLS handshake. During this period, you need to monitor its expiry date and ensure the full chain is served correctly.
- Renewal -- Before the certificate expires, you obtain a new one. Let's Encrypt certificates are valid for 90 days, and the recommended renewal window is 30 days before expiry. With certificate lifespans shrinking to 47 days, automated renewal is becoming a hard requirement rather than a convenience.
- Revocation -- If a private key is compromised or a certificate is issued in error, you revoke it immediately. Revocation tells clients the certificate should no longer be trusted, even if it has not expired.
The most common failure mode is not a sophisticated attack -- it is a certificate that quietly expires because nobody set up automated renewal.
Let's Encrypt Setup with Certbot
Certbot is the standard ACME client for Let's Encrypt. Install it from your distribution's package manager or via snap.
Nginx:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
Certbot modifies your Nginx server block to add the certificate paths and a redirect from HTTP to HTTPS. It stores certificates under /etc/letsencrypt/live/example.com/.
Apache:
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d example.com -d www.example.com
The Apache plugin configures the VirtualHost with the correct SSLCertificateFile, SSLCertificateKeyFile, and SSLCertificateChainFile directives automatically.
Standalone mode (when no web server plugin is available):
sudo certbot certonly --standalone -d example.com
This starts a temporary web server on port 80 for the ACME HTTP-01 challenge. Your existing web server must be stopped during this process, so standalone mode is best suited for initial issuance or environments where you manage the server configuration yourself.
Automated Renewal
Manual renewal does not scale and invites human error. Automate it.
Systemd timer (recommended on modern Linux):
Certbot's package typically installs a systemd timer at /etc/systemd/system/certbot.timer. Verify it is active:
sudo systemctl status certbot.timer
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
The timer runs certbot renew twice daily. Certbot only contacts Let's Encrypt when a certificate is within 30 days of expiry, so frequent runs are safe and encouraged.
Cron (alternative):
If your system does not use systemd, add a cron job:
echo "0 3,15 * * * root certbot renew --quiet --deploy-hook 'systemctl reload nginx'" | sudo tee /etc/cron.d/certbot-renew
The --deploy-hook flag is important. Certbot obtains the new certificate, but your web server continues to serve the old one from memory until it is reloaded. Without the hook, the renewal succeeds but the expired certificate remains in use until the next server restart.
For Apache, replace the hook with systemctl reload apache2.
Verify renewal works before you need it:
sudo certbot renew --dry-run
This simulates the entire renewal process without contacting Let's Encrypt. Run it after initial setup and after any server configuration change.
Certificate Chain Issues
A complete TLS certificate chain includes the leaf certificate (your domain), one or more intermediate certificates, and the root certificate. The server must send the leaf and all intermediates. The root is already in the client's trust store and should not be sent.
Missing intermediate certificates are the most common chain problem. The symptom is inconsistent: desktop Chrome often works because it caches intermediates, but mobile browsers, API clients, curl, and automated tools fail with a "certificate verify failed" error.
Diagnose chain problems with:
openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>&1 | openssl x509 -noout -text
Or use a more targeted check:
openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>&1 | grep -A 2 "Certificate chain"
You should see at least two certificates in the chain (your leaf certificate and the intermediate). If only one appears, your server configuration is missing the intermediate.
Fix for Nginx:
Concatenate the leaf and intermediate into a single file:
cat /etc/letsencrypt/live/example.com/fullchain.pem
Use fullchain.pem (not cert.pem) in your ssl_certificate directive. This is the single most common Nginx TLS misconfiguration. For the full protocol and cipher configuration that should accompany your certificate setup, see our TLS protocol and cipher hardening guide.
Fix for Apache:
Ensure SSLCertificateChainFile points to the intermediate certificate, or use the combined fullchain.pem with SSLCertificateFile.
OCSP Stapling
When a client receives your certificate, it may check whether the certificate has been revoked by querying the CA's OCSP responder. This adds latency to the handshake and leaks browsing information to the CA. OCSP stapling solves both problems: your server fetches and caches the OCSP response, then includes it in the TLS handshake.
Nginx configuration:
server {
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
}
Apache configuration:
SSLUseStapling On
SSLStaplingCache shmcb:/tmp/stapling_cache(128000)
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
Verify stapling is working:
openssl s_client -connect example.com:443 -servername example.com -status < /dev/null 2>&1 | grep -A 5 "OCSP Response"
A working response shows OCSP Response Status: successful. If it says "no response sent," stapling is not configured or the server has not yet fetched a response (restart the server and wait a moment).
Monitoring Certificate Expiry
Do not wait for a browser warning to discover an expired certificate.
CyberShield alerts: CyberShield's TLS scan checks certificate expiry as part of every assessment. Certificates expiring within 30 days are flagged as warnings, and certificates expiring within 7 days are flagged as critical findings. Schedule regular scans for all your domains to catch renewals that failed silently.
Command-line check:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
This prints the notBefore and notAfter dates. Parse the output in a script and alert when the expiry is within your renewal window.
Check from the certificate file directly:
openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
Quick days-remaining calculation:
expiry=$(openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem | cut -d= -f2)
days_left=$(( ( $(date -d "$expiry" +%s) - $(date +%s) ) / 86400 ))
echo "$days_left days remaining"
Integrate this into your monitoring system (Prometheus, Nagios, Datadog, or a simple cron-to-email script) and alert at 14 days remaining.
Emergency Renewal: What to Do When a Certificate Expires
If a certificate has already expired and users are seeing browser warnings, act immediately.
Step 1: Force renewal.
sudo certbot renew --force-renewal
The --force-renewal flag bypasses the 30-day window check and requests a new certificate immediately.
Step 2: Reload the web server.
sudo systemctl reload nginx # or apache2
The new certificate is on disk but will not be served until the web server picks it up.
Step 3: Verify the new certificate is live.
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
Confirm that notAfter shows a date 90 days in the future.
Step 4: Fix the root cause. An expired certificate means your automated renewal is broken. Check the systemd timer or cron job, review certbot logs at /var/log/letsencrypt/letsencrypt.log, and run certbot renew --dry-run to confirm the automation is restored.
Common reasons renewal fails silently: the deploy hook errors out, port 80 is blocked by a firewall rule (breaking the HTTP-01 challenge), DNS has changed and the domain no longer resolves to the server, or the certbot timer was disabled during a server migration and never re-enabled.
If certbot itself is failing, you can issue a certificate manually and install it while you debug:
sudo certbot certonly --standalone --preferred-challenges http -d example.com --force-renewal
Stop your web server first (standalone needs port 80), obtain the certificate, update your server config to point to the new cert paths, and start the web server again. Then fix the automation so this does not recur.
Prevention is always cheaper than an emergency. Automate renewal, monitor expiry, and test with --dry-run after every infrastructure change. For a structured approach to automation readiness, use our certificate lifecycle management checklist.
Continue Reading
Beyond the Padlock: What a TLS Audit Actually Reveals
The browser padlock means your connection is encrypted — but encryption alone does not mean secure. Here's what a proper TLS audit examines.
Short-Lived TLS Certificates: What the 47-Day Revolution Means for Your Security
The CA/Browser Forum has approved a dramatic reduction in TLS certificate lifespans from 398 days to just 47 days by 2029. Learn what this means for your certificate management, automation strategy, and how to prepare your infrastructure.
Certificate Lifecycle Management Checklist
A practical checklist for managing TLS certificates from issuance through renewal, covering inventory, automation, monitoring, and preparation for the transition to 47-day certificate lifespans.