Let's Encrypt automatisieren, damit man nie wieder an Zertifikate denken muss
Let's-Encrypt-Zertifikate sind 90 Tage gültig, kurz genug, dass manuelle Erneuerung unrealistisch ist und Automatisierung praktisch Pflicht wird. Die meisten Server, die ich übernehme, haben certbot renew tatsächlich schon in einem Cron-Job oder systemd-Timer, der Certbot-Installer richtet das standardmäßig ein. Was oft fehlt, ist der Rest des Bildes: sicherstellen, dass ein erneuertes Zertifikat von den Diensten, die es nutzen, auch tatsächlich übernommen wird, Domains behandeln, die ein Wildcard-Zertifikat brauchen, und von einem fehlgeschlagenen Renewal erfahren, bevor das Zertifikat abläuft, nicht danach.
Der Reload-Schritt, den alle vergessen
Wenn Certbot ein Zertifikat erneuert, schreibt es neue Dateien nach /etc/letsencrypt/live/example.com/. Das sagt Nginx, Postfix oder was auch immer das Zertifikat nutzt, von selbst nicht, dass es jetzt das neue verwenden soll. Die Lösung ist ein Deploy-Hook, ein Skript, das Certbot nach erfolgreichem Renewal ausführt:
certbot renew --deploy-hook "systemctl reload nginx"
Bei einem Setup, in dem mehrere Dienste Zertifikate nutzen, kann der Deploy-Hook mehr als eine Sache tun:
#!/bin/bash
# /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
systemctl reload nginx
systemctl reload postfix
systemctl reload dovecot
Alles in /etc/letsencrypt/renewal-hooks/deploy/ läuft automatisch nach jedem erfolgreichen Renewal, das ist also ein einmaliger Einrichtungsschritt, nicht etwas, das man sich alle 90 Tage merken muss.
Wildcard-Zertifikate brauchen DNS-01
Die Standard-Challenge HTTP-01 (Certbot legt vorübergehend eine Datei ab, die Let's Encrypt prüft) funktioniert nicht für Wildcard-Zertifikate, dafür braucht es die DNS-01-Challenge, die den Domain-Besitz über einen TXT-Record nachweist. Bei Providern mit einem Certbot-DNS-Plugin lässt sich das trotzdem vollständig automatisieren:
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d example.com -d '*.example.com'
Die Credentials-Datei enthält ein API-Token, das nur DNS-Änderungen erlaubt, Certbot legt den TXT-Record an, wartet auf die Propagierung und entfernt ihn nach erfolgreicher Validierung wieder, alles ohne manuelle Schritte. Das lohnt sich einzurichten, selbst wenn aktuell kein Wildcard-Zertifikat gebraucht wird, denn in dem Moment, in dem ein Projekt eines braucht (zum Beispiel eine neue Subdomain pro Kunde), wäre die Alternative eine manuelle DNS-01-Challenge alle 90 Tage, also genau die Art von wiederkehrender manueller Aufgabe, die irgendwann übersehen wird.
Fehlschläge erkennen, bevor es das Zertifikat tut
Ein still fehlschlagendes Renewal ist das eigentliche Risiko, Certbot kann wochenlang scheitern, bevor ein Zertifikat abläuft, da es bei jedem Lauf erneut versucht, und wenn niemand das beobachtet, ist die erste Spur eines Problems eine Browser-Warnung auf einer Produktionsseite. Eine einfache, wöchentlich laufende Prüfung fängt das früh ab:
#!/bin/bash
# cert-expiry-check.sh
for domain in example.com mail.example.com; do
expiry=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
days=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))
if [ "$days" -lt 14 ]; then
echo "WARNUNG: Zertifikat für $domain läuft in $days Tagen ab"
fi
done
Ein Zertifikat mit noch 14 Tagen Restlaufzeit, das aber alle 60 Tage erneuert werden sollte (Certbots Standard-Schwelle für Renewal), ist ein Zeichen, dass das Renewal still vor sich hin fehlschlägt, oft wegen einer geänderten Firewall-Regel, die die HTTP-01-Challenge blockiert, eines abgelaufenen DNS-API-Tokens für DNS-01, oder einer Domain, die woanders hin zeigt, ohne dass jemand Certbots Konfiguration angepasst hat.
Was "automatisiert" hier eigentlich bedeutet
Ein Renewal-Cron-Job, der existiert, aber keine Dienste neu lädt, die Domains nicht behandelt, die DNS-01 brauchen, und keine Möglichkeit hat, einen Fehlschlag sichtbar zu machen, ist nicht wirklich automatisiert, es ist ein Prozess mit einem implizit immer noch eingebundenen Menschen, nur einem, der von einem Problem erst erfährt, wenn ein Kunde es tut. Das eigentliche Ziel ist ein Setup, in dem das Erneuern eines Zertifikats, das Übernehmen des neuen Zertifikats durch den Dienst, und das Sichtbarwerden eines Fehlers in beiden Schritten, alles ohne dass sich jemand etwas auf einem 90-Tage-Zyklus merken muss, passiert. Ist das einmal eingerichtet, gehören Zertifikate zu den wenigen Dingen auf einem Server, die sich tatsächlich selbst kümmern.