💡 Hinweis: Dieses Tutorial setzt voraus, dass du einen normalen Benutzer mit sudo-Rechten verwendest — wie im Tutorial Debian 13 Server absichern beschrieben.

Einleitung — Warum HTTPS? Was ist Let’s Encrypt?

HTTPS ist heute kein optionales Extra mehr — es ist Pflicht. Browser wie Chrome und Firefox markieren unverschlüsselte Seiten als „Nicht sicher“, Suchmaschinen bevorzugen verschlüsselte Verbindungen im Ranking, und ohne TLS sind sensible Daten wie Login-Formulare oder Kontaktanfragen für jeden im Netzwerk im Klartext lesbar.

Let’s Encrypt ist eine kostenlose, automatisierte und offene Certificate Authority (CA), betrieben von der gemeinnützigen Internet Security Research Group (ISRG). Seit 2015 hat Let’s Encrypt Milliarden von Zertifikaten ausgestellt und damit HTTPS für alle zugänglich gemacht — ohne Kosten, ohne komplizierte Anträge.

In diesem Guide richten wir Let’s Encrypt SSL-Zertifikate auf einem Debian 13 (Trixie) Server mit Nginx ein — Schritt für Schritt, von der Installation bis zur automatischen Erneuerung, inklusive Wildcard-Zertifikaten und Hardening.

Voraussetzungen

Bevor wir starten, stelle sicher, dass Folgendes gegeben ist:

  • Debian 13 (Trixie) — frisch installiert oder bestehendes System
  • Nginx installiert und aktiv — falls noch nicht geschehen, folge Tutorial #2: Nginx auf Debian 13 installieren
  • Eine Domain, die per DNS A-Record (und/oder AAAA-Record) auf die öffentliche IP deines Servers zeigt
  • Port 80 und 443 müssen von außen erreichbar sein (Firewall/Security Groups prüfen)
  • Root-Zugang oder ein User mit sudo-Rechten

Alle Befehle in diesem Tutorial werden mit sudo ausgeführt.

Certbot installieren

Certbot ist das offizielle Tool von Let’s Encrypt zum Anfordern und Verwalten von Zertifikaten. Für Debian 13 gibt es mehrere Installationswege — hier die Übersicht:

Option 1: APT (empfohlen für Debian 13)

Debian 13 liefert eine aktuelle Certbot-Version in den offiziellen Repositories. Das ist der einfachste und sauberste Weg:

sudo apt update
sudo apt install certbot python3-certbot-nginx -y

Das Paket python3-certbot-nginx ist das Nginx-Plugin, das Certbot erlaubt, deine Nginx-Konfiguration automatisch anzupassen.

Option 2: Snap

Die EFF empfiehlt offiziell den Snap-Weg. Falls du Snap auf deinem Server nutzt:

sudo apt install snapd -y
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Der Vorteil: Certbot aktualisiert sich automatisch über Snap. Der Nachteil: Snap bringt einen eigenen Daemon (snapd) mit, den viele Server-Admins auf Minimalsystemen vermeiden wollen.

Option 3: pip (für Spezialfälle)

sudo apt install python3-venv -y
sudo python3 -m venv /opt/certbot
sudo /opt/certbot/bin/pip install certbot certbot-nginx
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot

Diese Methode ist sinnvoll, wenn du eine bestimmte Version brauchst oder auf exotischen Systemen arbeitest.

Meine Empfehlung

Für Debian 13 → Option 1 (APT). Sauber, einfach, wird über die regulären System-Updates mit gepflegt. Kein Snap-Overhead nötig.

Prüfe nach der Installation die Version:

sudo certbot --version

Erstes Zertifikat anfordern

Jetzt wird es ernst. Stelle sicher, dass deine Domain bereits auf den Server zeigt und Nginx läuft:

sudo systemctl status nginx
# Sollte "active (running)" anzeigen

Dann fordern wir das Zertifikat an. Certbot mit dem Nginx-Plugin erledigt fast alles automatisch:

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

Ersetze example.com durch deine tatsächliche Domain.

Was passiert dabei?

  1. Certbot prüft, ob Nginx läuft und findet die passende Server-Block-Konfiguration
  2. Es wird eine HTTP-01 Challenge durchgeführt: Let’s Encrypt stellt eine Anfrage an http://example.com/.well-known/acme-challenge/..., um zu verifizieren, dass du die Domain kontrollierst
  3. Nach erfolgreicher Validierung wird das Zertifikat ausgestellt und unter /etc/letsencrypt/live/example.com/ gespeichert
  4. Certbot passt deine Nginx-Konfiguration automatisch an

Beim ersten Aufruf wirst du nach einer E-Mail-Adresse gefragt (für Ablaufwarnungen) und musst die Nutzungsbedingungen akzeptieren. Für nicht-interaktive Nutzung (z. B. in Skripten):

sudo certbot --nginx -d example.com -d www.example.com \
  --non-interactive --agree-tos -m admin@example.com

Was Certbot an der Nginx-Config ändert

Nach dem erfolgreichen Zertifikats-Request hat Certbot deine Nginx-Konfiguration modifiziert. Schauen wir uns an, was sich geändert hat:

cat /etc/nginx/sites-available/example.com

Certbot fügt typischerweise folgende Zeilen in deinen server-Block ein:

server {
    server_name example.com www.example.com;

    # ... deine bestehende Konfiguration ...

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

Zusätzlich erstellt Certbot einen separaten Server-Block für die HTTP→HTTPS-Weiterleitung:

server {
    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name example.com www.example.com;
    return 404; # managed by Certbot
}

Die Dateien erklärt

DateiInhalt
fullchain.pemDein Zertifikat + Intermediate-Zertifikat der CA
privkey.pemDein privater Schlüssel — niemals teilen!
chain.pemNur das Intermediate-Zertifikat (für OCSP Stapling)
cert.pemNur dein Zertifikat (ohne Chain)
options-ssl-nginx.confCertbots SSL-Defaults (Protokolle, Ciphers)
ssl-dhparams.pemDiffie-Hellman-Parameter für Forward Secrecy

Wichtig: Die Dateien unter /etc/letsencrypt/live/ sind Symlinks. Die eigentlichen Zertifikate liegen in /etc/letsencrypt/archive/. Bei jeder Erneuerung werden die Symlinks automatisch aktualisiert — darum musst du in der Nginx-Config immer die Pfade aus live/ verwenden.

SSL-Konfiguration optimieren

Certbots Standard-Konfiguration ist solide, aber wir können sie noch weiter härten. Erstelle eine eigene SSL-Snippet-Datei:

sudo nano /etc/nginx/snippets/ssl-hardening.conf

Inhalt:

# Protokolle: Nur TLS 1.2 und 1.3
ssl_protocols TLSv1.2 TLSv1.3;

# Ciphers: Server bestimmt die Reihenfolge
ssl_prefer_server_ciphers on;

# Moderne Cipher-Suite (TLS 1.2)
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';

# TLS 1.3 Ciphers (werden separat konfiguriert, falls nötig)
# ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;

# ECDH-Kurve
ssl_ecdh_curve X25519:secp384r1;

# Session-Cache für Performance
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# OCSP Stapling — beschleunigt TLS-Handshake
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 9.9.9.9 valid=300s;
resolver_timeout 5s;

# Trusted Certificate für OCSP
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

Binde die Datei in deinen Server-Block ein:

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    include /etc/nginx/snippets/ssl-hardening.conf;

    # ... Rest der Konfiguration ...
}

Teste und lade Nginx neu:

sudo nginx -t
sudo systemctl reload nginx

Was bedeuten diese Einstellungen?

  • TLS 1.2+: TLS 1.0 und 1.1 sind offiziell veraltet (RFC 8996) und werden von modernen Browsern nicht mehr unterstützt
  • ssl_prefer_server_ciphers: Der Server bestimmt, welche Cipher verwendet wird — nicht der Client
  • ECDHE-Ciphers: Bieten Forward Secrecy — selbst wenn der private Schlüssel kompromittiert wird, bleiben vergangene Sessions sicher
  • OCSP Stapling: Der Server liefert den Gültigkeitsnachweis des Zertifikats gleich mit, statt dass der Browser die CA selbst fragen muss. Das ist schneller und datenschutzfreundlicher
  • ssl_session_tickets off: Session Tickets können Forward Secrecy untergraben, wenn der Ticket-Schlüssel kompromittiert wird

Automatische Erneuerung einrichten & testen

Let’s Encrypt-Zertifikate sind 90 Tage gültig. Das klingt kurz, ist aber Absicht: Es fördert Automatisierung und begrenzt den Schaden bei Kompromittierung. Certbot kümmert sich automatisch um die Erneuerung — wir müssen nur sicherstellen, dass es funktioniert.

Systemd Timer (Standard bei Debian 13)

Bei der Installation über APT wird automatisch ein Systemd-Timer angelegt:

sudo systemctl list-timers | grep certbot

Ausgabe (ähnlich):

NEXT                         LEFT     LAST                         PASSED  UNIT                ACTIVATES
Mon 2025-02-17 06:23:00 UTC  5h left  Sun 2025-02-16 18:23:00 UTC  6h ago  certbot.timer       certbot.service

Der Timer prüft zweimal täglich, ob ein Zertifikat erneuert werden muss (es wird erst erneuert, wenn weniger als 30 Tage Restlaufzeit übrig sind).

Dry-Run testen

Teste die Erneuerung, ohne tatsächlich ein neues Zertifikat anzufordern:

sudo certbot renew --dry-run

Wenn die Ausgabe Congratulations, all simulated renewals succeeded enthält, funktioniert alles.

Post-Renewal Hook: Nginx automatisch neu laden

Nach einer Erneuerung muss Nginx das neue Zertifikat laden. Certbot bietet dafür Deploy-Hooks:

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
sudo systemctl reload nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Alternativ kannst du den Hook auch in der Renewal-Konfiguration hinterlegen. Öffne /etc/letsencrypt/renewal/example.com.conf und füge hinzu:

[renewalparams]
# ...bestehende Parameter...
renew_hook = systemctl reload nginx

Wildcard-Zertifikate mit DNS-Challenge

Wildcard-Zertifikate (*.example.com) sichern alle Subdomains ab — praktisch, wenn du viele Subdomains hast oder dynamisch neue hinzufügst. Sie erfordern eine DNS-01 Challenge statt der üblichen HTTP-01.

Wie funktioniert DNS-01?

Certbot fordert dich auf, einen speziellen TXT-Record in deinem DNS anzulegen. Let’s Encrypt prüft diesen Record, um zu verifizieren, dass du die Domain kontrollierst.

Manuell (interaktiv)

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

Certbot gibt dir einen Wert vor, den du als DNS TXT-Record anlegen musst:

_acme-challenge.example.com  TXT  "zM3v7b..."

Lege den Record bei deinem DNS-Provider an, warte 1–2 Minuten auf Propagation und bestätige in Certbot.

Nachteil: Die manuelle Methode funktioniert nicht für automatische Erneuerung! Du müsstest alle 60–90 Tage den DNS-Record manuell aktualisieren.

Automatisch mit DNS-Plugin

Für automatische Erneuerung brauchst du ein DNS-Plugin, das den TXT-Record per API setzt. Die gängigsten:

DNS-ProviderPlugin-Paket
Cloudflarepython3-certbot-dns-cloudflare
Hetzner DNScertbot-dns-hetzner (pip)
DigitalOceanpython3-certbot-dns-digitalocean
Route53 (AWS)python3-certbot-dns-route53
Google Cloud DNSpython3-certbot-dns-google

Beispiel: Cloudflare

sudo apt install python3-certbot-dns-cloudflare -y

Erstelle eine Credentials-Datei:

sudo mkdir -p /etc/letsencrypt/secrets
sudo nano /etc/letsencrypt/secrets/cloudflare.ini
# Cloudflare API Token (empfohlen, eingeschränkte Rechte)
dns_cloudflare_api_token = dein-api-token-hier
sudo chmod 600 /etc/letsencrypt/secrets/cloudflare.ini

Zertifikat anfordern:

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/secrets/cloudflare.ini \
  -d "*.example.com" -d example.com

Da die DNS-Challenge automatisch funktioniert, klappt auch die automatische Erneuerung einwandfrei. Vergiss nicht, das Zertifikat in deiner Nginx-Konfiguration einzubinden:

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

Mehrere Domains absichern

Es gibt verschiedene Strategien, um mehrere Domains mit Let’s Encrypt abzusichern:

Strategie 1: Ein Zertifikat für mehrere Domains (SAN)

Du kannst bis zu 100 Domains in einem einzigen Zertifikat bündeln:

sudo certbot --nginx \
  -d example.com -d www.example.com \
  -d blog.example.com -d shop.example.com

Vorteil: Weniger Zertifikate zu verwalten, weniger Overhead.
Nachteil: Alle Domains sehen einander im Zertifikat (Transparenz). Erneuerung betrifft alle gleichzeitig.

Strategie 2: Separate Zertifikate pro Domain

sudo certbot --nginx -d example.com -d www.example.com
sudo certbot --nginx -d andere-domain.de -d www.andere-domain.de

Vorteil: Unabhängige Verwaltung, keine Domain-Sichtbarkeit untereinander.
Nachteil: Mehr Zertifikate, mehr Renewal-Jobs.

Strategie 3: Wildcard + Hauptdomain

sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/secrets/cloudflare.ini \
  -d "*.example.com" -d example.com

Vorteil: Ein Zertifikat für alle Subdomains, auch zukünftige.
Nachteil: Wildcard deckt keine Sub-Subdomains ab (*.sub.example.com braucht ein eigenes Zertifikat).

Rate Limits beachten

Let’s Encrypt hat Rate Limits:

  • 50 Zertifikate pro registrierter Domain pro Woche
  • 5 doppelte Zertifikate (gleiche Domain-Kombination) pro Woche
  • 300 neue Aufträge pro Konto pro 3 Stunden

Nutze --staging für Tests, um nicht an die Limits zu stoßen:

sudo certbot --nginx --staging -d test.example.com

SSL-Test: Qualität prüfen

Nach der Einrichtung solltest du die Qualität deiner SSL-Konfiguration prüfen.

SSL Labs (Online)

Der bekannteste Test: Qualys SSL Labs Server Test

Gib deine Domain ein und warte 1–2 Minuten. Ziel ist ein A+-Rating. Mit unserer gehärteten Konfiguration und HSTS (nächstes Kapitel) erreichst du das.

testssl.sh (Lokal)

Für einen detaillierten lokalen Test installiere testssl.sh:

sudo apt install testssl.sh -y

Oder direkt von GitHub:

git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh

Ausführen:

testssl --fast example.com

Oder ausführlicher:

testssl --full example.com

testssl.sh prüft unter anderem:

  • Unterstützte Protokolle und Ciphers
  • Bekannte Schwachstellen (Heartbleed, POODLE, ROBOT, etc.)
  • Zertifikatskette und Gültigkeit
  • HSTS, OCSP Stapling, Certificate Transparency

Schnellcheck mit OpenSSL

Für einen schnellen Blick auf das Zertifikat:

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

OCSP Stapling prüfen:

echo | openssl s_client -connect example.com:443 -servername example.com -status 2>/dev/null | grep -A 5 "OCSP Response"

HSTS einrichten

HTTP Strict Transport Security (HSTS) weist Browser an, deine Domain ausschließlich über HTTPS aufzurufen — auch wenn jemand http:// eintippt. Der Browser leitet intern um, bevor er überhaupt eine HTTP-Anfrage stellt.

Füge den Header in deinen SSL-Server-Block ein:

server {
    listen 443 ssl;
    # ...

    # HSTS — Browser merkt sich für 1 Jahr: nur HTTPS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}

Die Parameter erklärt

  • max-age=31536000: Browser merkt sich die HSTS-Policy für 1 Jahr (in Sekunden)
  • includeSubDomains: Gilt auch für alle Subdomains
  • preload: Ermöglicht die Aufnahme in die HSTS Preload List — Browser erzwingen HTTPS schon beim allerersten Besuch

⚠️ Risiken und Warnungen

HSTS ist schwer rückgängig zu machen! Wenn du HSTS mit max-age=31536000 aktivierst und dann HTTPS abschaltest, ist deine Seite für bis zu ein Jahr unerreichbar für Besucher, die den HSTS-Header schon empfangen haben.

Empfohlenes Vorgehen:

  1. Starte mit einem kurzen max-age (z. B. 300 = 5 Minuten) zum Testen
  2. Prüfe, ob alles funktioniert (keine Mixed-Content-Warnings, alle Subdomains per HTTPS erreichbar)
  3. Erhöhe schrittweise: 3600 → 86400 → 604800 → 2592000 → 31536000
  4. includeSubDomains erst hinzufügen, wenn alle Subdomains HTTPS unterstützen
  5. preload erst ganz am Ende, wenn du dir sicher bist — die Aufnahme in die Preload List kann Monate dauern, das Entfernen ebenso
# Phase 1: Testen (5 Minuten)
add_header Strict-Transport-Security "max-age=300" always;

# Phase 2: Produktiv (1 Jahr, mit Subdomains)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Phase 3: Preload (erst wenn 100% sicher)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

HTTP → HTTPS Redirect (301)

Certbot richtet normalerweise automatisch eine Weiterleitung ein. Falls du sie manuell konfigurieren oder anpassen willst:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # Permanente Weiterleitung zu HTTPS
    return 301 https://$host$request_uri;
}

Warum 301 und nicht 302?

  • 301 (Permanent): Browser und Suchmaschinen merken sich die Weiterleitung. Suchmaschinen übertragen den SEO-Wert auf die HTTPS-URL
  • 302 (Temporary): Nur für temporäre Weiterleitungen. Suchmaschinen behalten die HTTP-URL im Index

Für die HTTPS-Migration ist 301 immer die richtige Wahl.

ACME-Challenge nicht umleiten

Wichtig: Die Let’s Encrypt HTTP-01 Challenge läuft über Port 80. Falls du einen sehr strikten Redirect konfigurierst, stelle sicher, dass der Challenge-Pfad erreichbar bleibt:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # ACME Challenge erlauben
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # Alles andere → HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

Certbot regelt das normalerweise automatisch — aber es ist gut zu wissen, falls du die Config manuell verwaltest.

Zusammenfassung & Checkliste

Hier die komplette Checkliste als Schnellreferenz:

  • ☐ Debian 13 und Nginx installiert
  • ☐ Domain zeigt per A/AAAA-Record auf den Server
  • ☐ Port 80 und 443 in der Firewall offen
  • ☐ Certbot + Nginx-Plugin installiert (sudo apt install certbot python3-certbot-nginx)
  • ☐ Zertifikat angefordert (sudo certbot --nginx -d domain.tld)
  • ☐ SSL-Konfiguration gehärtet (TLS 1.2+, starke Ciphers, OCSP Stapling)
  • ☐ Automatische Erneuerung getestet (sudo certbot renew --dry-run)
  • ☐ Deploy-Hook für Nginx-Reload eingerichtet
  • ☐ HTTP → HTTPS Redirect aktiv (301)
  • ☐ HSTS-Header gesetzt (schrittweise erhöhen!)
  • ☐ SSL-Test durchgeführt (SSL Labs → A+)

Die wichtigsten Pfade

PfadBeschreibung
/etc/letsencrypt/live/domain/Aktuelle Zertifikate (Symlinks)
/etc/letsencrypt/archive/domain/Alle Zertifikats-Versionen
/etc/letsencrypt/renewal/domain.confRenewal-Konfiguration
/etc/letsencrypt/renewal-hooks/Pre/Post/Deploy-Hooks
/etc/letsencrypt/options-ssl-nginx.confCertbots SSL-Defaults
/var/log/letsencrypt/letsencrypt.logCertbot-Logdatei

Troubleshooting

Problem: Zertifikat ist abgelaufen

Prüfe zuerst, warum die automatische Erneuerung nicht funktioniert hat:

# Timer aktiv?
sudo systemctl status certbot.timer

# Letzte Logs prüfen
sudo journalctl -u certbot.service --since "7 days ago"

# Manuell erneuern
sudo certbot renew --force-renewal

Problem: Renewal schlägt fehl — „Connection refused“ oder Timeout

Die häufigste Ursache: Port 80 ist blockiert.

# Firewall prüfen (iptables)
iptables -L -n | grep 80

# Firewall prüfen (nftables/ufw)
sudo ufw status
nft list ruleset | grep 80

# Ist Nginx auf Port 80 erreichbar?
curl -I http://example.com

Falls Port 80 nicht nutzbar ist (z. B. durch Corporate Firewall), kannst du auf die DNS-Challenge umsteigen (siehe Kapitel Wildcard-Zertifikate).

Problem: „Too many certificates already issued“

Du hast das Rate Limit erreicht. Warte eine Woche oder nutze die Staging-Umgebung für Tests:

sud certbot --staging --nginx -d example.com

Problem: Nginx startet nicht nach Certbot-Änderung

# Konfiguration prüfen
sudo nginx -t

# Häufige Fehler:
# - Doppelter listen 443 ssl; in verschiedenen Configs
# - Zertifikatspfad existiert nicht
# - Syntax-Fehler durch manuelle Bearbeitung nach Certbot

Problem: OCSP Stapling funktioniert nicht

# Prüfen
echo | openssl s_client -connect example.com:443 -status 2>/dev/null | grep "OCSP Response Status"

# Häufige Ursachen:
# 1. Resolver nicht konfiguriert → resolver 1.1.1.1 hinzufügen
# 2. ssl_trusted_certificate fehlt oder zeigt auf falsche Datei
# 3. Firewall blockiert ausgehende Verbindungen zu OCSP-Servern

Problem: Mixed Content nach HTTPS-Migration

Browser blockiert Ressourcen, die noch über HTTP geladen werden (Bilder, Scripts, CSS). Lösungen:

  • In der Datenbank/CMS alle URLs von http:// auf https:// ändern
  • Oder den CSP-Header upgrade-insecure-requests setzen:

    add_header Content-Security-Policy "upgrade-insecure-requests" always;

Nützliche Debug-Befehle

# Alle Certbot-Zertifikate auflisten
sudo certbot certificates

# Zertifikat-Details anzeigen
sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -text

# Ablaufdatum prüfen
sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -enddate

# Let's Encrypt Account-Info
sudo certbot show_account

Nächste Schritte

Dein Server ist jetzt mit einem kostenlosen, automatisch erneuerten SSL-Zertifikat abgesichert. Hier einige Ideen für die nächsten Schritte:

  • Security Headers — Neben HSTS gibt es weitere wichtige HTTP-Security-Header: X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Content-Security-Policy, Permissions-Policy
  • HTTP/2 und HTTP/3 — Nginx unterstützt HTTP/2 out of the box (listen 443 ssl http2;) und experimentell HTTP/3 via QUIC
  • Monitoring — Richte Zertifikats-Monitoring ein (z. B. mit Checkmk, UptimeRobot oder einem eigenen Script), um rechtzeitig gewarnt zu werden
  • CAA-Record — Setze einen DNS CAA-Record, der festlegt, welche CAs Zertifikate für deine Domain ausstellen dürfen:

    example.com. CAA 0 issue "letsencrypt.org"
  • Certificate Transparency Logs — Überwache mit crt.sh, welche Zertifikate für deine Domain ausgestellt wurden

Viel Erfolg mit deinem abgesicherten Server! Bei Fragen oder Problemen hinterlasse gerne einen Kommentar.