P1MediumRunbook

Emergency Certificate Replacement

Certificate expired or compromised? This runbook gets you back online FAST. Follow these steps to minimize downtime.

15-30 minutes
Last Updated: December 2025
Progress: 0/33 complete0%

When to Use

  • Certificate has expired and site is showing errors
  • Certificate needs immediate replacement (not scheduled)
  • Site is down due to certificate issues

Do NOT Use For

  • Private key was compromised (use Key Compromise Response Runbook first)
  • Scheduled renewal (use Certificate Renewal Runbook for proper planning)

Quick Reference (TL;DR)

  1. Assess: What broke? Which cert? Expired or compromised?
  2. Get new cert: Let's Encrypt (fastest) or emergency CA issuance
  3. Deploy and reload web server
  4. Verify HTTPS is working
  5. Document what happened

1Assess the Situation

Objective: Quickly understand what broke and notify stakeholders

Check certificate status:

# Check expiration and issuer
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
  openssl x509 -noout -subject -issuer -dates

# If connection fails, check what error
curl -vI https://example.com 2>&1 | head -20

2Option A: Deploy Backup Certificate

Objective: If you have a valid backup certificate, deploy it immediately

Verify backup cert is valid:

openssl x509 -in backup-cert.pem -noout -dates -subject

💡 If backup exists and is valid, this is the FASTEST option

💡 Skip to "Deploy" section with backup certificate

3Option B: Let's Encrypt (Fastest for Public Sites)

Objective: Issue a free DV certificate in minutes

Standalone mode (stop web server first, uses port 80):

# Stop web server temporarily
sudo systemctl stop nginx  # or apache2

# Get certificate
sudo certbot certonly --standalone -d example.com -d www.example.com

# Restart web server
sudo systemctl start nginx

Webroot mode (web server keeps running):

sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com

Using acme.sh (alternative):

# Install if needed: curl https://get.acme.sh | sh

acme.sh --issue -d example.com -d www.example.com --webroot /var/www/html

# Or DNS validation (works even if web server is down)
acme.sh --issue -d example.com --dns dns_cloudflare

💡 Let's Encrypt issues in under 1 minute

💡 Rate limits: 50 certs per domain per week, 5 failures per hour

💡 Certificates are valid for 90 days

4Option C: Emergency CA Issuance

Objective: Contact your CA for expedited issuance

Generate emergency CSR (if needed):

openssl req -new -newkey rsa:2048 -nodes \
  -keyout emergency.key -out emergency.csr \
  -subj "/CN=example.com"

💡 Most CAs offer free reissuance/replacement

💡 DV certificates can issue in minutes with email/HTTP validation

💡 OV/EV may take longer unless pre-validated

💡 Call CA support if portal is slow: DigiCert, Sectigo, GlobalSign all have 24/7 support

5Deploy Certificate

Objective: Install the new certificate and get the site back online

Create certificate bundle:

cat new-cert.crt intermediate.crt > bundle.crt

nginx - test and reload:

sudo nginx -t && sudo systemctl reload nginx

Apache - test and reload:

sudo apachectl configtest && sudo systemctl reload apache2

HAProxy:

cat new-cert.key bundle.crt > /etc/haproxy/certs/site.pem
sudo haproxy -c -f /etc/haproxy/haproxy.cfg && sudo systemctl reload haproxy

IIS (PowerShell):

# Import PFX
$password = ConvertTo-SecureString -String "yourpassword" -Force -AsPlainText
Import-PfxCertificate -FilePath "C:\certs\newcert.pfx" -CertStoreLocation Cert:\LocalMachine\My -Password $password

# Update binding (get thumbprint from import output)
# Use IIS Manager or: netsh http update sslcert ipport=0.0.0.0:443 certhash=THUMBPRINT appid={APPID}

6Verify Fix

Objective: Confirm the site is back online with valid certificate

Quick verification:

# Check new certificate
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
  openssl x509 -noout -dates

# Verify chain is complete
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
  grep "Verify return code"

# Should show: Verify return code: 0 (ok)

Full chain check:

curl -vI https://example.com 2>&1 | grep -A5 "Server certificate"

7Post-Incident

Objective: Document and prevent recurrence

Rollback Procedure

  1. If new certificate causes issues, restore backup certificate
  2. Check web server error logs for specific failure reason
  3. Verify key and certificate match: openssl x509 -noout -modulus -in cert.pem | md5sum && openssl rsa -noout -modulus -in key.pem | md5sum
  4. Contact CA support if certificate appears invalid

Troubleshooting

Problem: Let's Encrypt rate limit hit

Solution: Use staging environment to test, or wait 1 hour (failure limit) / 1 week (certificate limit)

Problem: Cannot complete domain validation

Solution: Check DNS propagation, firewall rules, or use DNS-01 challenge instead of HTTP-01

Problem: Certificate works in browser but API clients fail

Solution: Check intermediate chain is included, some clients don't fetch missing intermediates

Problem: Key and certificate don't match

Solution: Generate new CSR with the new key and reissue - cannot mix keys and certs

Escalation

Internal: Contact your security/infrastructure team lead

CA Support: DigiCert: 1-801-877-2100 | Sectigo: 1-888-266-6361 | GlobalSign: 1-877-775-4562

After Hours: Follow your organization's on-call escalation procedures