Certificate expiration is the outage you always see coming and somehow never prevent. Here’s how to automate SSL so it stops being a problem.

The Problem

SSL certificates expire. When they do:

  • Users see scary browser warnings
  • APIs reject connections
  • Mobile apps fail silently
  • Trust is broken

And it’s always on a Friday night.

Let’s Encrypt + Certbot

Free, automated, trusted certificates.

Basic Setup

1
2
3
4
5
6
7
8
# Install certbot
apt install certbot python3-certbot-nginx

# Get certificate (nginx plugin handles everything)
certbot --nginx -d example.com -d www.example.com

# Test renewal
certbot renew --dry-run

Certbot adds a cron job automatically for renewal.

DNS Challenge for Wildcards

1
2
certbot certonly --manual --preferred-challenges dns \
  -d "*.example.com" -d example.com

You’ll need to add a TXT record to prove domain ownership.

Kubernetes Cert-Manager

Install

1
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml

ClusterIssuer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx

Ingress Annotation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls-secret
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app
                port:
                  number: 80

Cert-manager watches for this annotation and handles everything.

AWS Certificate Manager

For AWS services (ALB, CloudFront, API Gateway):

1
2
3
4
aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names "*.example.com" \
  --validation-method DNS

ACM certificates auto-renew. Use them wherever AWS supports them.

Monitoring Certificates

Check Expiration

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

Prometheus Alert

1
2
3
4
5
6
7
- alert: SSLCertExpiringSoon
  expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 14
  for: 1h
  labels:
    severity: warning
  annotations:
    summary: "SSL cert expires in {{ $value | humanizeDuration }}"

Common Mistakes

1. Not Including All Domains

1
2
3
4
5
# Bad: Missing www
certbot --nginx -d example.com

# Good: Include all variants
certbot --nginx -d example.com -d www.example.com

2. Forgetting to Reload

1
2
# Reload after renewal
certbot renew --post-hook "systemctl reload nginx"

3. Wrong Certificate Chain

1
2
3
# Good: Full chain
ssl_certificate /etc/ssl/fullchain.pem;
ssl_certificate_key /etc/ssl/privkey.pem;

The SSL Automation Checklist

  • Automated issuance (Let’s Encrypt / ACM)
  • Automated renewal (certbot cron / cert-manager)
  • Reload/restart after renewal
  • Full certificate chain configured
  • Expiration monitoring
  • Alerts at 14 days before expiry

SSL should be invisible. If you’re thinking about certificates, something’s wrong.


The best SSL automation is the one you forget exists — until you realize you haven’t had a certificate emergency in years.