Zum Inhalt springen

SSL-Zertifikat einrichten und automatisch erneuern

Let's Encrypt per ACME einrichten, Wildcard-Zertifikate über DNS validieren, HSTS bewusst setzen und die typischen Mixed-Content-Reste nach der Umstellung aufräumen.

Zuletzt geprüft: Gedacht für: HTTPS-Umstellung und Verlängerung

Das Wichtigste

  • Let's-Encrypt-Zertifikate laufen 90 Tage. Ohne funktionierende Automatik ist der Ausfall nur eine Frage der Zeit.
  • Wildcard-Zertifikate brauchen zwingend die DNS-Validierung – die HTTP-Validierung reicht dafür nicht aus.
  • HSTS ist praktisch nicht zurücknehmbar. Erst setzen, wenn HTTPS auf allen betroffenen Hosts sicher funktioniert.
  • Nach der Umstellung bleiben fast immer Mixed-Content-Reste in der Datenbank – Bild- und Skriptpfade mit http://.

HTTPS ist seit Jahren die Voraussetzung dafür, dass eine Seite überhaupt normal funktioniert – von der Standortabfrage bis zum Passwortmanager. Die Einrichtung ist inzwischen unspektakulär; interessant sind die Stellen, an denen sie später bricht.

Einrichtung mit certbot

# Apache, HTTP-Validierung
certbot --apache -d example.com -d www.example.com

# nginx
certbot --nginx -d example.com -d www.example.com

certbot legt dabei das Zertifikat an, trägt es in die Serverkonfiguration ein und richtet die automatische Erneuerung als systemd-Timer oder Cronjob ein.

Prüfen, ob die Automatik wirklich läuft:

systemctl list-timers | grep certbot
certbot renew --dry-run

Der Probelauf ist der Punkt, den man nicht überspringt. Er durchläuft die vollständige Validierung ohne ein Zertifikat auszustellen und zeigt genau die Fehler, die in 60 Tagen sonst produktiv auftreten.

Wildcard-Zertifikate

Ein Zertifikat für *.example.com erfordert die DNS-Validierung – die HTTP-Variante ist dafür nicht zugelassen:

certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

Der Anbieter braucht ein Plugin für deinen DNS-Dienst. Existiert keines, geht es über einen manuellen Hook, der den TXT-Eintrag per API setzt – dann muss zwischen Setzen und Prüfen eine Wartezeit eingebaut sein, sonst schlägt die Validierung fehl, weil der Eintrag noch nicht verteilt ist.

Ist die Subdomainliste überschaubar und stabil, ist ein Zertifikat mit mehreren Namen die einfachere Lösung: Es kommt ohne DNS-Zugriff aus.

Die Stolperfalle: der Challenge-Pfad

Zur HTTP-Validierung legt certbot eine Datei unter /.well-known/acme-challenge/ ab und die Prüfstelle ruft sie ab. Drei Konfigurationen brechen das:

Verzeichnisschutz über dem gesamten Webroot. Die Prüfung bekommt ein 401 statt der Datei:

# Ausnahme innerhalb des geschützten Bereichs
<IfModule mod_authz_core.c>
  <Files "*">
    Require all denied
  </Files>
</IfModule>
# und in .well-known/acme-challenge/.htaccess:
Require all granted

Eine allumfassende Rewrite-Regel vor der Ausnahme:

RewriteEngine On
# muss VOR der Anwendungsregel stehen
RewriteRule ^\.well-known/acme-challenge/ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

Eine Weiterleitung auf HTTPS, wenn das Zertifikat noch gar nicht existiert. Der Challenge-Pfad muss über HTTP erreichbar bleiben.

HSTS: mit Bedacht

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Der Header weist Browser an, die Domain für ein Jahr ausschliesslich über HTTPS anzusprechen. Das ist ein echter Sicherheitsgewinn und praktisch nicht zurücknehmbar: Wer den Header entfernt, erreicht damit nur neue Besucher – alle anderen haben ihn gespeichert.

Vor dem Setzen:

  • HTTPS funktioniert auf allen Hosts der Domain zuverlässig.
  • includeSubDomains nur setzen, wenn jede Subdomain ein gültiges Zertifikat hat, auch interne Testsysteme.
  • Mit einem kurzen max-age von einigen Tagen anfangen und erst nach einigen Wochen erhöhen.
  • Die Aufnahme in die Preload-Liste ist eine separate, noch schwerer umkehrbare Entscheidung.

Mixed Content aufräumen

Nach der Umstellung bleiben in gewachsenen Projekten fast immer absolute http://-URLs in der Datenbank:

-- vorher zählen
SELECT COUNT(*) FROM wp_posts WHERE post_content LIKE '%http://example.com%';

-- ersetzen
UPDATE wp_posts
   SET post_content = REPLACE(post_content, 'http://example.com', 'https://example.com');

Vorher eine Sicherung ziehen. Und aufpassen bei serialisierten Daten: In WordPress-Optionen und vielen Plugin-Tabellen stehen PHP-Arrays als Zeichenkette mit Längenangabe. Ein einfaches REPLACE verändert die Länge, ohne die Angabe anzupassen – die Daten sind danach unlesbar. Dafür gibt es Werkzeuge, die serialisierte Strukturen korrekt neu schreiben.

Die verbliebenen Stellen findet die Browser-Konsole:

// alle Ressourcen, die über HTTP geladen wurden
performance.getEntriesByType('resource')
  .filter(r => r.name.startsWith('http://'))
  .map(r => r.name);

Nach der Umstellung nicht vergessen

  • Weiterleitung von HTTP auf HTTPS und die Kanonisierung zwischen www und Apex – beides sind zwei getrennte Regeln.
  • Canonical-Angaben und Sitemap auf https:// umstellen.
  • In der Search Console die HTTPS-Property anlegen und die Sitemap dort einreichen.
  • Externe Dienste mit hinterlegter URL aktualisieren: Zahlungsdienste, Webhooks, Verzeichnisse.
  • Eine Erinnerung setzen, die 30 Tage vor Ablauf prüft, ob die Automatik gegriffen hat.

Häufige Fragen

Kostet ein SSL-Zertifikat Geld?

Für die Verschlüsselung nicht: Let's Encrypt stellt domainvalidierte Zertifikate kostenlos aus, und sie sind technisch gleichwertig zu bezahlten DV-Zertifikaten. Bezahlt werden bei kommerziellen Anbietern die erweiterte Prüfung, Garantien und Support – für eine normale Webseite ist das nicht nötig.

Warum schlägt meine Zertifikatserneuerung fehl?

Die häufigste Ursache ist ein Verzeichnisschutz oder eine Weiterleitung, die den Pfad unter /.well-known/acme-challenge/ abfängt. Dieser Pfad muss ohne Anmeldung und ohne Umleitung erreichbar sein. Zweithäufigste Ursache: eine Firewallregel, die den Prüfserver blockiert.

Brauche ich ein Wildcard-Zertifikat?

Nur bei vielen oder dynamisch entstehenden Subdomains. Für eine überschaubare, feste Liste ist ein Zertifikat mit mehreren Namen einfacher, weil es ohne DNS-Validierung auskommt.

Was ist Mixed Content?

Eine über HTTPS ausgelieferte Seite, die Ressourcen über HTTP nachlädt. Browser blockieren Skripte und Stylesheets in diesem Fall vollständig, Bilder werden je nach Einstellung geladen und lösen eine Warnung aus. Die Ursache steckt meist in absoluten URLs in der Datenbank.