← Back to Blog

SSL Certificate Renewal: Complete Guide (Avoid Downtime)

An expired SSL certificate causes an immediate, visible outage - browsers block users with a full-page warning, APIs refuse to connect, and SEO rankings drop. Yet certificate expiry is entirely preventable with a proper renewal and monitoring strategy. This guide covers everything from checking expiry dates to emergency recovery.

The Problem: Why Certificates Expire Unexpectedly

Modern SSL/TLS certificates from Let's Encrypt have a 90-day validity period. Commercial certificates from DigiCert, Sectigo, and others typically run for 1-2 years (the CA/Browser Forum capped new certificates at 398 days in 2020). Despite these well known validity windows, certificate expiry remains one of the most common causes of web outages.

The reasons vary: the engineer who originally set up the certificate has left the company and nobody else knows where it lives; the renewal reminder emails go to a generic inbox that nobody monitors; the auto-renewal cron job silently failed months ago; or the certificate was manually installed on a load balancer that was later rebuilt. In every case, the result is the same: a jarring warning page that drives users away and triggers incident alerts.

In 2020, a major US government agency's COVID-19 response website went down for hours due to an expired certificate. In 2023, Microsoft Teams experienced a global outage partly attributed to certificate mismanagement. Certificate expiry causes real, costly incidents at organisations of every size.

Step 1: Check Your Current Certificate Expiry

Before setting up automation, audit what you have. There are several ways to check a certificate's expiry date:

From the Command Line (openssl)

# Check expiry for any domain
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates

# Output:
# notBefore=Mar  1 00:00:00 2026 GMT
# notAfter=May 30 00:00:00 2026 GMT

# Check days remaining (Linux/macOS)
expiry=$(echo | openssl s_client -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -enddate | cut -d= -f2)
days=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))
echo "Certificate expires in $days days"

Check a Local Certificate File

openssl x509 -in /etc/ssl/certs/example.com.crt -noout -dates
openssl x509 -in /etc/ssl/certs/example.com.crt -noout -subject -issuer -dates

Check All Let's Encrypt Certificates

sudo certbot certificates
# Lists all managed certificates, their domains, expiry dates, and certificate paths

Check Any Domain's SSL Certificate

Instantly inspect certificate expiry, issuer, TLS version, cipher suite, and HSTS headers for any domain. Free, no account needed.

Open SSL Checker

Step 2: Set Up Automated Renewal with Certbot

Let's Encrypt certificates are free and renew automatically with Certbot. If you are not already using Let's Encrypt, start here. If you are using a commercial CA, skip to the monitoring section.

Install Certbot

# Ubuntu/Debian
sudo apt update && sudo apt install certbot python3-certbot-nginx

# CentOS/RHEL
sudo dnf install certbot python3-certbot-nginx

# macOS (via Homebrew)
brew install certbot

Issue Your First Certificate (Nginx)

# Certbot automatically configures Nginx
sudo certbot --nginx -d example.com -d www.example.com

# Or obtain only (configure Nginx manually)
sudo certbot certonly --nginx -d example.com -d www.example.com

Test Auto-Renewal

# Dry run - simulates renewal without making changes
sudo certbot renew --dry-run

# If successful, you see:
# Congratulations, all simulated renewals succeeded

Verify the Auto-Renewal Timer

Certbot installs a systemd timer (or cron job) that runs twice daily. Verify it is active:

# Check systemd timer status
sudo systemctl status certbot.timer
sudo systemctl list-timers | grep certbot

# Enable if not already enabled
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

# On older systems using cron
cat /etc/cron.d/certbot
# Should contain something like:
# 0 */12 * * * root certbot renew --quiet

Post-Renewal Hook (Reload Web Server)

Certbot can automatically reload Nginx or Apache after renewal so the new certificate is picked up without manual intervention:

# Create a post-renewal hook
sudo nano /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh

#!/bin/bash
systemctl reload nginx

sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh

Step 3: Wildcard Certificate Renewal (DNS Challenge)

Wildcard certificates (e.g., *.example.com) cover all subdomains but require DNS-01 challenge validation - you cannot use the HTTP-01 challenge. This means your DNS provider must support API-based record creation.

# Install the DNS plugin for your provider (example: Cloudflare)
sudo pip3 install certbot-dns-cloudflare

# Create Cloudflare credentials file
sudo nano /etc/letsencrypt/cloudflare.ini
# dns_cloudflare_api_token = your_api_token_here
sudo chmod 600 /etc/letsencrypt/cloudflare.ini

# Issue wildcard certificate
sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d example.com \
  -d "*.example.com"

# Renewal is automatic via the same credentials

DNS plugin packages exist for Route53 (certbot-dns-route53), Google Cloud DNS (certbot-dns-google), DigitalOcean (certbot-dns-digitalocean), and most major providers.

Step 4: Monitoring and Alerting Before Expiry

Automation can fail silently. Always add independent monitoring as a safety net.

Bash Script with Email Alert

#!/bin/bash
# ssl-monitor.sh - alert if certificate expires within 30 days

DOMAIN="example.com"
THRESHOLD=30
ALERT_EMAIL="ops@example.com"

expiry=$(echo | openssl s_client -connect $DOMAIN:443 -servername $DOMAIN 2>/dev/null \
  | openssl x509 -noout -enddate | cut -d= -f2)
days=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))

if [ $days -lt $THRESHOLD ]; then
  echo "WARNING: $DOMAIN certificate expires in $days days ($expiry)" \
    | mail -s "SSL EXPIRY ALERT: $DOMAIN" $ALERT_EMAIL
  echo "Alert sent for $DOMAIN ($days days remaining)"
fi
# Add to crontab - run daily at 08:00
0 8 * * * /usr/local/bin/ssl-monitor.sh >> /var/log/ssl-monitor.log 2>&1

Using External Monitoring Services

  • Uptime Robot (free) - monitors SSL expiry with 30-day email alerts
  • StatusCake (free tier) - SSL monitoring with Slack/PagerDuty integration
  • Datadog - built-in SSL check with configurable alert thresholds
  • Grafana + Blackbox Exporter - self-hosted, Prometheus-based SSL monitoring
  • AWS Certificate Manager - auto-renews ACM certificates, sends CloudWatch events 45 and 30 days before expiry

Prometheus + Alertmanager Rule

# prometheus-rules.yml
groups:
  - name: ssl
    rules:
      - alert: SSLCertExpiringSoon
        expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "SSL certificate expiring soon for {{ $labels.instance }}"
          description: "Certificate expires in {{ $value | humanizeDuration }}"

Step 5: Commercial Certificate Renewal (Manual Process)

For OV (Organisation Validated) or EV (Extended Validation) certificates from commercial CAs, renewal involves human verification and cannot be fully automated. The process:

  1. Generate a new CSR (Certificate Signing Request) from your server:
# Generate a new private key and CSR
openssl req -new -newkey rsa:2048 -nodes \
  -keyout example.com.key \
  -out example.com.csr \
  -subj "/C=US/ST=California/L=San Francisco/O=Example Inc/CN=example.com"

# View the CSR to confirm contents
openssl req -in example.com.csr -noout -text
  1. Submit the CSR to your CA (DigiCert, Sectigo, etc.) via their web portal
  2. Complete domain validation (email, DNS record, or HTTP file challenge)
  3. For OV/EV: complete organisation verification (may take 1-3 business days)
  4. Download the new certificate bundle from the CA portal
  5. Install on your server and reload the web server

Start commercial certificate renewal at least 30 days before expiry to account for OV/EV verification time. Calendar reminders are unreliable - use external monitoring tools as your primary early-warning system.

Emergency Recovery: Certificate Already Expired

If you discover your certificate has already expired and your site is showing a browser warning, act immediately:

# Option 1: Force immediate Certbot renewal (if using Let's Encrypt)
sudo certbot renew --force-renewal
sudo systemctl reload nginx

# Option 2: Issue a brand new certificate if the old one can't be renewed
sudo certbot --nginx -d example.com -d www.example.com
sudo systemctl reload nginx

# Verify the new certificate is live
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

If users are blocked by browser warnings, they may not be able to reach your site at all. Keep an out-of-band communication channel (status page on a separate domain, Slack, email) ready to notify users during recovery.

Certificate Pinning: When It Complicates Renewal

Some mobile apps implement certificate pinning - hardcoding the expected certificate fingerprint into the app binary. If you renew your certificate (which changes the fingerprint), pinned clients will refuse to connect until users update the app. Consider pinning to the CA intermediate certificate or the public key hash (HPKP) rather than the leaf certificate, or avoid pinning altogether for public APIs where renewal agility is more important than the added security.

Frequently Asked Questions

How often does Certbot try to renew certificates?

The Certbot timer runs twice daily. However, it only actually renews a certificate when it is within 30 days of expiry (for Let's Encrypt certificates). Let's Encrypt's 90-day validity plus 30-day renewal window means you always have a substantial buffer. You can confirm by running sudo certbot renew --dry-run and checking the output.

Can I renew a certificate before it expires?

Yes. You can force early renewal with certbot renew --force-renewal or certbot certonly --force-renew. This is useful when you need to add a new subdomain to an existing certificate or after rotating your private key following a security incident. Let's Encrypt enforces rate limits (5 certificates per domain per week), so avoid unnecessary forced renewals.

What happens to existing connections when the certificate is renewed?

Nothing - until the web server reloads. Active connections continue with the old certificate until they close naturally. After systemctl reload nginx (or Apache), new connections use the new certificate. The reload itself is graceful and does not drop existing connections. The transition is invisible to users.

My site is behind a CDN (Cloudflare, CloudFront). Do I still need to renew?

For traffic served by the CDN, the CDN's own certificate is what users see, and major CDNs manage their certificates automatically. However, the origin certificate - the one between your CDN and your server - still needs to be renewed. Cloudflare Origin Certificates are valid for up to 15 years; AWS ACM certificates auto-renew. Check your specific CDN's documentation to confirm what requires manual action.

What is ACME and how does it relate to Let's Encrypt and Certbot?

ACME (Automatic Certificate Management Environment) is the protocol (RFC 8555) that Let's Encrypt uses for automated certificate issuance and renewal. Certbot is a client that implements the ACME protocol. Other ACME clients include acme.sh (shell script, popular for its flexibility), Caddy (built-in ACME, zero-config HTTPS), Traefik (automatic HTTPS for containerised services), and cert-manager (Kubernetes-native ACME client). Any ACME-compatible CA can be used, not just Let's Encrypt.

The Bottom Line

SSL certificate renewal is a solved problem. Let's Encrypt and Certbot handle the renewal cycle fully automatically for most setups, with minimal configuration. For commercial certificates, external monitoring services provide the 30-60 day warning window you need to complete manual renewal before users are affected. The only unacceptable approach is relying on calendar reminders or manual checks - those always fail eventually.

Start by auditing your current certificates today: Use our SSL Checker tool here →

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.