{"id":128,"date":"2026-06-14T16:21:06","date_gmt":"2026-06-14T16:21:06","guid":{"rendered":"https:\/\/shattered.io\/de\/2026\/06\/14\/nginx-reverse-proxy-https-einrichten\/"},"modified":"2026-06-14T16:22:36","modified_gmt":"2026-06-14T16:22:36","slug":"nginx-reverse-proxy-https-einrichten","status":"publish","type":"post","link":"https:\/\/shattered.io\/de\/2026\/06\/14\/nginx-reverse-proxy-https-einrichten\/","title":{"rendered":"Nginx Reverse Proxy: HTTPS in 12 Schritten [2026]"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Ein <strong>Nginx Reverse Proxy<\/strong> sitzt zwischen dem Internet und Ihren Backend-Anwendungen. Er nimmt jede Anfrage entgegen, beendet die TLS-Verschl\u00fcsselung, filtert Angriffe und reicht nur saubere Requests an Ihre Dienste weiter. Laut W3Techs l\u00e4uft rund ein Drittel aller aktiven Websites auf Nginx, was den Server zur meistgenutzten Reverse-Proxy-L\u00f6sung im professionellen Hosting macht. Diese Anleitung f\u00fchrt Sie in zw\u00f6lf Schritten von der leeren Ubuntu-Installation zu einem produktionsreifen Reverse Proxy mit HTTPS, Let&#8217;s-Encrypt-Zertifikat, modernen Sicherheits-Headern und Rate-Limiting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wir arbeiten mit Ubuntu 26.04 LTS (&#8220;Resolute Raccoon&#8221;, ver\u00f6ffentlicht am 23. April 2026), dem stabilen Nginx-Zweig und Certbot. Jeder Schritt enth\u00e4lt die exakten Befehle, vollst\u00e4ndige Konfigurationsbl\u00f6cke und Beispiel-Ausgaben. Am Ende finden Sie eine komplette Beispielkonfiguration, f\u00fcnf h\u00e4ufige Stolperfallen, eine Troubleshooting-Tabelle mit acht Eintr\u00e4gen sowie fortgeschrittene Tipps f\u00fcr hohe Last und mehrere Backends.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"was-ist-ein-nginx-reverse-proxy-und-warum-brauchen-sie-ihn\">Was ist ein Nginx Reverse Proxy und warum brauchen Sie ihn?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Forward Proxy handelt im Auftrag des Clients, ein <strong>Reverse Proxy<\/strong> handelt im Auftrag des Servers. Der Client spricht ausschlie\u00dflich mit Nginx und wei\u00df nichts von den dahinterliegenden Anwendungen. Diese Architektur bringt vier konkrete Vorteile, die Sie in dieser Anleitung alle umsetzen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>TLS-Terminierung an einer Stelle.<\/strong> Ihre Node.js-, Python- oder PHP-Anwendung muss sich nicht um Zertifikate k\u00fcmmern. Nginx beendet die HTTPS-Verbindung, das Backend bekommt entschl\u00fcsseltes HTTP auf localhost. Das spart Rechenzeit im Backend und zentralisiert die Zertifikatsverwaltung. Mehr zur Funktionsweise von Transportverschl\u00fcsselung lesen Sie in unserem Beitrag zu <a href=\"\/https-und-tls\/\">HTTPS und TLS<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sicherheit und Angriffsfl\u00e4che.<\/strong> Das Backend lauscht nur auf 127.0.0.1 und ist aus dem Internet nicht erreichbar. Nginx wird zur einzigen exponierten Komponente, die Sie h\u00e4rten, mit Rate-Limiting sch\u00fctzen und mit Sicherheits-Headern absichern. Eine kompromittierte Anwendung kann nicht direkt von au\u00dfen erreicht werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Lastverteilung und Skalierung.<\/strong> Ein <code>upstream<\/code>-Block b\u00fcndelt mehrere Backend-Instanzen. Nginx verteilt Anfragen per Round-Robin, Least-Connections oder IP-Hash und nimmt ausgefallene Knoten automatisch aus der Rotation. So skalieren Sie horizontal, ohne die Client-Konfiguration zu \u00e4ndern.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Performance.<\/strong> Nginx liefert statische Dateien direkt aus, komprimiert Antworten mit Gzip oder Brotli, cached Responses und multiplext Verbindungen \u00fcber HTTP\/2 und HTTP\/3. Das Backend wird entlastet und antwortet schneller. Genau diese Konstellation, ein einziger geh\u00e4rteter Eingangspunkt vor beliebig vielen Diensten, macht den Reverse Proxy zum Standard moderner Web-Architekturen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"voraussetzungen-versionen-und-systemanforderungen\">Voraussetzungen: Versionen und Systemanforderungen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Bevor Sie starten, brauchen Sie einen Server mit \u00f6ffentlicher IP-Adresse und eine Domain, die Sie auf diese IP zeigen lassen k\u00f6nnen. Die folgende Tabelle listet alle Komponenten mit den in dieser Anleitung verwendeten Versionen. Halten Sie sich an aktuelle stabile Releases, da viele Sicherheitsfixes nur in neueren Versionen landen.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Komponente<\/th><th>Version \/ Anforderung<\/th><th>Zweck<\/th><\/tr><\/thead><tbody><tr><td>Betriebssystem<\/td><td>Ubuntu 26.04 LTS oder 24.04 LTS<\/td><td>Server-Basis (Debian funktioniert analog)<\/td><\/tr><tr><td>Nginx<\/td><td>Stabiler Zweig 1.28 oder neuer<\/td><td>Reverse Proxy, TLS, HTTP\/2 und HTTP\/3<\/td><\/tr><tr><td>Certbot<\/td><td>2.0 oder neuer (via snap)<\/td><td>Let&#8217;s-Encrypt-Zertifikate per ACME<\/td><\/tr><tr><td>OpenSSL<\/td><td>3.0 oder neuer<\/td><td>TLS-Bibliothek, Schl\u00fcsselgenerierung<\/td><\/tr><tr><td>Domain<\/td><td>A\/AAAA-Record auf Server-IP<\/td><td>Voraussetzung f\u00fcr HTTP-01-Validierung<\/td><\/tr><tr><td>Offene Ports<\/td><td>80 (HTTP) und 443 (HTTPS)<\/td><td>ACME-Challenge und Produktivverkehr<\/td><\/tr><tr><td>Zugriff<\/td><td>SSH mit sudo-Rechten<\/td><td>Installation und Konfiguration<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr den SSH-Zugang empfehlen wir Schl\u00fcssel statt Passw\u00f6rter. Falls Sie noch keinen erzeugt haben, folgen Sie unserer Anleitung zum <a href=\"\/ssh-key-erstellen-ed25519\/\">SSH-Key mit Ed25519<\/a>. Pr\u00fcfen Sie au\u00dferdem vorab, dass Ihre Domain bereits auf die Server-IP aufl\u00f6st, sonst scheitert die Zertifikatsausstellung in Schritt 7.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-1-system-aktualisieren-und-nginx-installieren\">Schritt 1: System aktualisieren und Nginx installieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Bringen Sie zuerst das Paketverzeichnis auf den neuesten Stand und installieren Sie alle ausstehenden Sicherheitsupdates. Anschlie\u00dfend installieren Sie Nginx aus den Ubuntu-Repositories. Wer die allerneuesten Features ben\u00f6tigt, kann das offizielle Nginx-Repository einbinden, f\u00fcr die meisten Reverse-Proxy-Szenarien reicht das Distributionspaket.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update && sudo apt upgrade -y\nsudo apt install nginx -y\n\n# Version pr\u00fcfen\nnginx -v<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Ausgabe best\u00e4tigt die installierte Version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nginx version: nginx\/1.28.0 (Ubuntu)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Aktivieren Sie den Dienst, damit er nach jedem Neustart automatisch l\u00e4uft, und pr\u00fcfen Sie den Status:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl enable --now nginx\nsudo systemctl status nginx --no-pager<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Sie sollten <code>active (running)<\/code> sehen. Rufen Sie nun die \u00f6ffentliche IP Ihres Servers im Browser auf. Die Standard-Willkommensseite von Nginx best\u00e4tigt, dass der Server Anfragen auf Port 80 beantwortet. Erscheint nichts, blockiert vermutlich die Firewall den Port, was wir im n\u00e4chsten Schritt beheben.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-2-firewall-konfigurieren-ufw\">Schritt 2: Firewall konfigurieren (UFW)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die Uncomplicated Firewall (UFW) ist auf Ubuntu vorinstalliert. \u00d6ffnen Sie die f\u00fcr einen Reverse Proxy n\u00f6tigen Ports und sperren Sie alles andere. Nginx registriert beim Setup ein UFW-Profil, das Sie direkt nutzen k\u00f6nnen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># SSH erlauben, damit Sie sich nicht aussperren\nsudo ufw allow OpenSSH\n\n# HTTP und HTTPS freigeben\nsudo ufw allow 'Nginx Full'\n\n# Firewall aktivieren\nsudo ufw enable\nsudo ufw status verbose<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Das Profil <code>Nginx Full<\/code> \u00f6ffnet Port 80 und 443 gleichzeitig. Die erwartete Ausgabe:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Status: active\n\nTo                         Action      From\n--                         ------      ----\nOpenSSH                    ALLOW IN    Anywhere\nNginx Full                 ALLOW IN    Anywhere<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Geben Sie immer zuerst <code>OpenSSH<\/code> frei, bevor Sie UFW aktivieren. Andernfalls kappt die Firewall Ihre laufende SSH-Sitzung und Sie verlieren den Zugriff auf einen entfernten Server. Wer eine vorgelagerte Hardware- oder Cloud-Firewall einsetzt, sollte dort dieselben Ports freigeben. F\u00fcr komplexere Netzwerk-Topologien vergleichen wir Firewall-Distributionen im Beitrag zu <a href=\"\/opnsense-vs-pfsense\/\">OPNsense vs pfSense<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-3-backend-anwendung-vorbereiten\">Schritt 3: Backend-Anwendung vorbereiten<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Der Reverse Proxy braucht einen Dienst, an den er weiterleitet. Zum Testen starten wir eine simple Node.js-Anwendung auf Port 3000, die nur auf localhost lauscht. In der Praxis ersetzen Sie dies durch Ihre echte Anwendung, das Prinzip bleibt identisch: Das Backend bindet sich an 127.0.0.1, nicht an 0.0.0.0.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ app.js\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n  res.writeHead(200, { 'Content-Type': 'text\/plain; charset=utf-8' });\n  res.end('Hallo vom Backend auf Port 3000\\n');\n});\n\n\/\/ WICHTIG: nur an localhost binden, nicht an 0.0.0.0\nserver.listen(3000, '127.0.0.1', () => {\n  console.log('Backend laeuft auf http:\/\/127.0.0.1:3000');\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Starten Sie die Anwendung und pr\u00fcfen Sie lokal mit curl, dass sie antwortet:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node app.js &\ncurl http:\/\/127.0.0.1:3000\n# Ausgabe: Hallo vom Backend auf Port 3000<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Indem das Backend ausschlie\u00dflich auf 127.0.0.1 lauscht, ist es aus dem Internet nicht direkt erreichbar. Selbst wenn ein Angreifer Port 3000 in der Firewall offen findet, bekommt er keine Verbindung, weil der Dienst nur lokale Sockets akzeptiert. Im Produktivbetrieb verwalten Sie den Prozess mit systemd, PM2 oder Docker, damit er nach einem Absturz oder Neustart automatisch wieder hochf\u00e4hrt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-4-grundlegende-reverse-proxy-konfiguration\">Schritt 4: Grundlegende Reverse-Proxy-Konfiguration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Jetzt erstellen Sie die erste <code>server<\/code>-Konfiguration. Legen Sie pro Domain eine Datei unter <code>\/etc\/nginx\/sites-available\/<\/code> an und verlinken Sie sie nach <code>sites-enabled\/<\/code>. Diese Trennung erlaubt es, eine Site zu deaktivieren, ohne ihre Konfiguration zu l\u00f6schen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/nginx\/sites-available\/example.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcgen Sie die folgende Konfiguration ein. Ersetzen Sie <code>example.com<\/code> durch Ihre Domain. Wir definieren einen <code>upstream<\/code>-Block, damit ein sp\u00e4terer Wechsel auf mehrere Backends nur eine Zeile betrifft.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>upstream backend_app {\n    server 127.0.0.1:3000;\n    keepalive 32;\n}\n\nserver {\n    listen 80;\n    listen [::]:80;\n    server_name example.com www.example.com;\n\n    location \/ {\n        proxy_pass http:\/\/backend_app;\n        proxy_http_version 1.1;\n\n        # Original-Header an das Backend weitergeben\n        proxy_set_header Host              $host;\n        proxy_set_header X-Real-IP         $remote_addr;\n        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header Connection        \"\";\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die <code>proxy_set_header<\/code>-Direktiven sind entscheidend. Ohne <code>Host<\/code> bekommt das Backend einen falschen Hostnamen, ohne <code>X-Forwarded-For<\/code> sieht es nur die IP des Proxys statt die des echten Clients. Aktivieren Sie die Site, testen Sie die Syntax und laden Sie Nginx neu:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ln -s \/etc\/nginx\/sites-available\/example.conf \/etc\/nginx\/sites-enabled\/\nsudo nginx -t\nsudo systemctl reload nginx<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der Befehl <code>nginx -t<\/code> liefert bei korrekter Syntax:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nginx: configuration file \/etc\/nginx\/nginx.conf syntax is ok\nnginx: configuration file \/etc\/nginx\/nginx.conf test is successful<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Rufen Sie nun Ihre Domain \u00fcber HTTP auf. Statt der Nginx-Willkommensseite erscheint jetzt die Antwort des Backends. Der Reverse Proxy funktioniert, allerdings noch unverschl\u00fcsselt. Das \u00e4ndern wir in den n\u00e4chsten Schritten.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-5-dns-und-domain-richtig-setzen\">Schritt 5: DNS und Domain richtig setzen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Damit Let&#8217;s Encrypt ein Zertifikat ausstellt, muss Ihre Domain auf die Server-IP zeigen. Legen Sie bei Ihrem DNS-Anbieter einen A-Record (IPv4) und idealerweise einen AAAA-Record (IPv6) an. Pr\u00fcfen Sie die Aufl\u00f6sung von einem anderen Rechner aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dig +short example.com A\ndig +short example.com AAAA\n\n# Erwartete Ausgabe: Ihre Server-IP, z. B.\n# 203.0.113.10<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">DNS-\u00c4nderungen brauchen je nach TTL Minuten bis Stunden, bis sie weltweit greifen. Warten Sie, bis <code>dig<\/code> die korrekte IP zur\u00fcckgibt, bevor Sie Certbot starten. Die HTTP-01-Challenge von Let&#8217;s Encrypt schl\u00e4gt fehl, solange die Validierungsserver Ihre Domain nicht auf den richtigen Host aufl\u00f6sen. Setzen Sie sowohl <code>example.com<\/code> als auch <code>www.example.com<\/code>, damit das Zertifikat beide Varianten abdeckt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-6-certbot-installieren\">Schritt 6: Certbot installieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die EFF empfiehlt die Installation von Certbot \u00fcber snap, weil Sie so immer die aktuelle Version mit allen Plugins erhalten. Entfernen Sie eventuell vorhandene apt-Pakete, um Konflikte zu vermeiden, und installieren Sie das snap.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Eventuelle alte Pakete entfernen\nsudo apt remove certbot -y\n\n# Certbot via snap installieren\nsudo snap install --classic certbot\nsudo ln -s \/snap\/bin\/certbot \/usr\/bin\/certbot\n\ncertbot --version\n# Ausgabe: certbot 2.x oder neuer<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Certbot spricht das ACME-Protokoll mit den Servern von Let&#8217;s Encrypt, der weltweit gr\u00f6\u00dften Zertifizierungsstelle. Let&#8217;s Encrypt stellt Domain-validierte Zertifikate kostenlos aus und hat damit HTTPS f\u00fcr Millionen Websites zug\u00e4nglich gemacht. Das nginx-Plugin von Certbot kann Ihre Konfiguration automatisch anpassen, was wir im n\u00e4chsten Schritt nutzen. Details zur Organisation finden Sie auf der <a href=\"https:\/\/letsencrypt.org\/\" target=\"_blank\" rel=\"noopener\">offiziellen Let&#8217;s-Encrypt-Seite<\/a> und zur Installation in der <a href=\"https:\/\/certbot.eff.org\/\" target=\"_blank\" rel=\"noopener\">Certbot-Dokumentation<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-7-https-mit-lets-encrypt-aktivieren\">Schritt 7: HTTPS mit Let&#8217;s Encrypt aktivieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Jetzt stellen Sie das Zertifikat aus und lassen Certbot die HTTPS-Weiterleitung einrichten. Das nginx-Plugin liest Ihre <code>server_name<\/code>-Eintr\u00e4ge, holt das Zertifikat per HTTP-01-Challenge und schreibt die TLS-Direktiven direkt in Ihre Konfiguration.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo certbot --nginx -d example.com -d www.example.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Certbot fragt nach einer E-Mail-Adresse f\u00fcr Ablaufwarnungen und ob HTTP auf HTTPS umgeleitet werden soll. W\u00e4hlen Sie die Umleitung. Die Erfolgsmeldung sieht so aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Successfully received certificate.\nCertificate is saved at: \/etc\/letsencrypt\/live\/example.com\/fullchain.pem\nKey is saved at:         \/etc\/letsencrypt\/live\/example.com\/privkey.pem\nThis certificate expires on 2026-09-12.\nDeploying certificate\nSuccessfully deployed certificate for example.com\nCongratulations! You have successfully enabled HTTPS on https:\/\/example.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Standard-Zertifikate von Let&#8217;s Encrypt sind 90 Tage g\u00fcltig. 2025 f\u00fchrte die Zertifizierungsstelle zus\u00e4tzlich ein Profil f\u00fcr kurzlebige Zertifikate mit nur sechs Tagen G\u00fcltigkeit ein, das die Angriffsfl\u00e4che kompromittierter Schl\u00fcssel weiter verkleinert. Im selben Jahr stellte Let&#8217;s Encrypt die OCSP-Unterst\u00fctzung ein und setzt f\u00fcr Sperrinformationen auf CRLs. F\u00fcr die meisten Reverse-Proxy-Setups bleiben die regul\u00e4ren 90-Tage-Zertifikate die richtige Wahl, weil sie sich vollautomatisch erneuern lassen (siehe Schritt 12).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rufen Sie Ihre Domain jetzt mit <code>https:\/\/<\/code> auf. Das Schloss-Symbol im Browser best\u00e4tigt die verschl\u00fcsselte Verbindung. Was hinter diesem Symbol steckt, erkl\u00e4ren wir ausf\u00fchrlich im Beitrag zu <a href=\"\/https-und-tls\/\">HTTPS und TLS<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-8-tls-haerten-protokolle-und-cipher-suites\">Schritt 8: TLS h\u00e4rten (Protokolle und Cipher Suites)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Certbot hinterlegt eine solide Grundkonfiguration, doch f\u00fcr maximale Sicherheit h\u00e4rten Sie TLS manuell. Deaktivieren Sie veraltete Protokolle und beschr\u00e4nken Sie sich auf moderne Cipher Suites. Die folgende Tabelle zeigt, welche Protokolle Sie 2026 aktivieren und welche Sie abschalten sollten.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Protokoll<\/th><th>Status 2026<\/th><th>Empfehlung<\/th><\/tr><\/thead><tbody><tr><td>TLS 1.3<\/td><td>Aktueller Standard<\/td><td>Aktivieren (bevorzugt)<\/td><\/tr><tr><td>TLS 1.2<\/td><td>Weit verbreitet<\/td><td>Aktivieren (Kompatibilit\u00e4t)<\/td><\/tr><tr><td>TLS 1.1<\/td><td>Veraltet, unsicher<\/td><td>Deaktivieren<\/td><\/tr><tr><td>TLS 1.0<\/td><td>Veraltet, unsicher<\/td><td>Deaktivieren<\/td><\/tr><tr><td>SSLv3 \/ SSLv2<\/td><td>Gebrochen<\/td><td>Deaktivieren<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Erstellen Sie eine wiederverwendbare TLS-Konfiguration, die Sie in jeden HTTPS-Server einbinden. Die Werte orientieren sich am &#8220;Intermediate&#8221;-Profil des Mozilla SSL Configuration Generators, das einen guten Kompromiss aus Sicherheit und Kompatibilit\u00e4t bietet.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/nginx\/snippets\/tls-hardening.conf<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code># Nur moderne Protokolle\nssl_protocols TLSv1.2 TLSv1.3;\n\n# TLS 1.2 Cipher Suites (TLS 1.3 nutzt eigene, feste Suites)\nssl_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;\nssl_prefer_server_ciphers off;\n\n# Session-Handling\nssl_session_timeout 1d;\nssl_session_cache shared:SSL:10m;\nssl_session_tickets off;\n\n# Sichere Kurven\nssl_ecdh_curve X25519:secp384r1;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Binden Sie das Snippet in Ihren HTTPS-Server ein, indem Sie <code>include \/etc\/nginx\/snippets\/tls-hardening.conf;<\/code> in den <code>server<\/code>-Block schreiben. Nach <code>nginx -t<\/code> und <code>reload<\/code> pr\u00fcfen Sie Ihre Konfiguration mit dem kostenlosen <a href=\"https:\/\/www.ssllabs.com\/ssltest\/\" target=\"_blank\" rel=\"noopener\">SSL Labs Server Test<\/a>. Ziel ist die Note A oder A+. Die exakten Cipher-Listen f\u00fcr jedes Profil generiert der <a href=\"https:\/\/ssl-config.mozilla.org\/\" target=\"_blank\" rel=\"noopener\">Mozilla SSL Configuration Generator<\/a> passend zu Ihrer Nginx- und OpenSSL-Version.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-9-http-sicherheits-header-setzen\">Schritt 9: HTTP-Sicherheits-Header setzen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Sicherheits-Header weisen den Browser an, wie er mit Ihrer Seite umgehen soll. Sie sch\u00fctzen vor Clickjacking, Protokoll-Downgrades und Cross-Site-Scripting. Das OWASP Secure Headers Project pflegt eine aktuelle Liste der empfohlenen Header. Die folgende Tabelle fasst die wichtigsten zusammen.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Header<\/th><th>Empfohlener Wert<\/th><th>Schutz vor<\/th><\/tr><\/thead><tbody><tr><td>Strict-Transport-Security<\/td><td>max-age=63072000; includeSubDomains<\/td><td>Protokoll-Downgrade, SSL-Stripping<\/td><\/tr><tr><td>X-Frame-Options<\/td><td>SAMEORIGIN<\/td><td>Clickjacking<\/td><\/tr><tr><td>X-Content-Type-Options<\/td><td>nosniff<\/td><td>MIME-Type-Sniffing<\/td><\/tr><tr><td>Content-Security-Policy<\/td><td>default-src &#8216;self&#8217;<\/td><td>Cross-Site-Scripting (XSS)<\/td><\/tr><tr><td>Referrer-Policy<\/td><td>strict-origin-when-cross-origin<\/td><td>Metadaten-Leaks<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Legen Sie ein zweites Snippet an und binden Sie es ebenfalls in Ihren HTTPS-Server ein:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/nginx\/snippets\/security-headers.conf<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains\" always;\nadd_header X-Frame-Options \"SAMEORIGIN\" always;\nadd_header X-Content-Type-Options \"nosniff\" always;\nadd_header Referrer-Policy \"strict-origin-when-cross-origin\" always;\nadd_header Content-Security-Policy \"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'\" always;\n# Server-Version verbergen\nserver_tokens off;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Das Schl\u00fcsselwort <code>always<\/code> sorgt daf\u00fcr, dass die Header auch bei Fehlerseiten (4xx, 5xx) gesendet werden. Setzen Sie HSTS mit <code>max-age=63072000<\/code> (zwei Jahre) erst, wenn HTTPS zuverl\u00e4ssig l\u00e4uft, denn der Browser merkt sich die Anweisung und verweigert danach unverschl\u00fcsselte Verbindungen. Die <code>Content-Security-Policy<\/code> ist die wirksamste, aber auch komplexeste Direktive. Beginnen Sie restriktiv und erweitern Sie sie gezielt um die Quellen, die Ihre Anwendung wirklich ben\u00f6tigt. Als Referenz dient das <a href=\"https:\/\/owasp.org\/www-project-secure-headers\/\" target=\"_blank\" rel=\"noopener\">OWASP Secure Headers Project<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-10-rate-limiting-gegen-brute-force-und-ddos\">Schritt 10: Rate-Limiting gegen Brute-Force und DDoS<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Rate-Limiting begrenzt, wie viele Anfragen ein Client pro Zeiteinheit stellen darf. Das bremst Brute-Force-Angriffe auf Login-Seiten und mildert einfache DDoS-Versuche. Nginx nutzt daf\u00fcr <code>limit_req_zone<\/code> (definiert eine geteilte Speicherzone) und <code>limit_req<\/code> (wendet das Limit an). Die Zonendefinition geh\u00f6rt in den <code>http<\/code>-Block in <code>\/etc\/nginx\/nginx.conf<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># In \/etc\/nginx\/nginx.conf, innerhalb von http { ... }\n\n# Allgemeine Zone: 10 Anfragen\/Sekunde pro IP\nlimit_req_zone $binary_remote_addr zone=general:10m rate=10r\/s;\n\n# Strenge Zone fuer Login-Endpunkte: 1 Anfrage\/Sekunde\nlimit_req_zone $binary_remote_addr zone=login:10m rate=1r\/s;\n\n# Maximale gleichzeitige Verbindungen pro IP\nlimit_conn_zone $binary_remote_addr zone=conn_limit:10m;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Wenden Sie die Limits in den passenden <code>location<\/code>-Bl\u00f6cken an. Der <code>burst<\/code>-Parameter erlaubt kurze Lastspitzen, <code>nodelay<\/code> verarbeitet diese sofort statt verz\u00f6gert.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>location \/ {\n    limit_req zone=general burst=20 nodelay;\n    limit_conn conn_limit 10;\n    proxy_pass http:\/\/backend_app;\n}\n\nlocation \/login {\n    limit_req zone=login burst=5 nodelay;\n    proxy_pass http:\/\/backend_app;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u00dcberschreitet ein Client das Limit, antwortet Nginx mit Status 503 (oder 429, wenn Sie <code>limit_req_status 429;<\/code> setzen). Im Error-Log erscheint dann ein Eintrag wie dieser:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2026\/06\/14 10:22:41 [error] 8123#8123: *44 limiting requests,\nexcess: 20.500 by zone \"login\", client: 198.51.100.23,\nserver: example.com, request: \"POST \/login HTTP\/2.0\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">W\u00e4hlen Sie die Raten an Ihrem echten Traffic-Muster orientiert. Zu strenge Limits sperren legitime Nutzer aus, zu lockere bieten kaum Schutz. Rate-Limiting ersetzt keine dedizierte Web Application Firewall, ist aber eine wirksame erste Verteidigungslinie direkt im Reverse Proxy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-11-http-2-und-http-3-quic-aktivieren\">Schritt 11: HTTP\/2 und HTTP\/3 (QUIC) aktivieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">HTTP\/2 multiplext mehrere Anfragen \u00fcber eine Verbindung und beschleunigt das Laden sp\u00fcrbar. HTTP\/3 setzt auf QUIC \u00fcber UDP und eliminiert das Head-of-Line-Blocking auf Transportebene. Nginx unterst\u00fctzt HTTP\/3 seit Version 1.25.0 (Mai 2023), in aktuellen stabilen Releases ist es enthalten. HTTP\/2 aktivieren Sie mit dem <code>http2<\/code>-Parameter, HTTP\/3 zus\u00e4tzlich \u00fcber einen <code>listen<\/code>-Eintrag auf UDP-Port 443.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    # HTTP\/2 ueber TCP 443\n    listen 443 ssl;\n    listen [::]:443 ssl;\n    http2 on;\n\n    # HTTP\/3 ueber UDP 443 (QUIC)\n    listen 443 quic reuseport;\n    listen [::]:443 quic reuseport;\n\n    server_name example.com www.example.com;\n\n    # Browser auf HTTP\/3 hinweisen\n    add_header Alt-Svc 'h3=\":443\"; ma=86400' always;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Geben Sie f\u00fcr HTTP\/3 zus\u00e4tzlich UDP-Port 443 in der Firewall frei: <code>sudo ufw allow 443\/udp<\/code>. Der <code>Alt-Svc<\/code>-Header signalisiert dem Browser, dass HTTP\/3 verf\u00fcgbar ist. Beim n\u00e4chsten Besuch wechselt er automatisch auf QUIC. Verwenden Sie <code>reuseport<\/code> nur einmal pro Adresse und Port, sonst lehnt Nginx den Start ab.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-12-automatische-zertifikatserneuerung-einrichten\">Schritt 12: Automatische Zertifikatserneuerung einrichten<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s-Encrypt-Zertifikate laufen nach 90 Tagen ab. Certbot installiert beim Setup einen systemd-Timer, der zweimal t\u00e4glich pr\u00fcft, ob eine Erneuerung f\u00e4llig ist, und sie bei Bedarf durchf\u00fchrt. Testen Sie diesen Mechanismus mit einem Trockenlauf, bevor Sie sich darauf verlassen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Erneuerung simulieren, ohne ein echtes Zertifikat anzufordern\nsudo certbot renew --dry-run\n\n# Timer-Status pruefen\nsudo systemctl list-timers | grep certbot<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der Trockenlauf endet mit einer Erfolgsmeldung pro Zertifikat:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Congratulations, all simulated renewals succeeded:\n  \/etc\/letsencrypt\/live\/example.com\/fullchain.pem (success)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Damit Nginx das erneuerte Zertifikat l\u00e4dt, muss der Dienst nach der Erneuerung neu geladen werden. Certbot erledigt das \u00fcber einen Deploy-Hook. Setzen Sie ihn global, damit jede Erneuerung Nginx automatisch neu l\u00e4dt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Deploy-Hook fuer alle Erneuerungen setzen\nsudo sh -c 'echo \"deploy_hook = systemctl reload nginx\" >> \/etc\/letsencrypt\/cli.ini'\n\n# Mit Hook testen\nsudo certbot renew --deploy-hook \"systemctl reload nginx\" --dry-run<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ab jetzt erneuert sich Ihr Zertifikat vollautomatisch und Nginx \u00fcbernimmt es ohne manuelles Eingreifen. Damit ist der Reverse Proxy produktionsreif: verschl\u00fcsselt, automatisch wartbar und gegen die h\u00e4ufigsten Angriffe geh\u00e4rtet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"komplettes-konfigurationsbeispiel\">Komplettes Konfigurationsbeispiel<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Hier ist die vollst\u00e4ndige, produktionsreife Konfiguration, die alle vorherigen Schritte zusammenf\u00fchrt. Sie leitet HTTP auf HTTPS um, terminiert TLS, setzt Sicherheits-Header, limitiert Anfragen und unterst\u00fctzt HTTP\/2 sowie HTTP\/3.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>upstream backend_app {\n    server 127.0.0.1:3000;\n    keepalive 32;\n}\n\n# HTTP: alles auf HTTPS umleiten\nserver {\n    listen 80;\n    listen [::]:80;\n    server_name example.com www.example.com;\n    return 301 https:\/\/$host$request_uri;\n}\n\n# HTTPS: Reverse Proxy mit TLS, Headern und Rate-Limiting\nserver {\n    listen 443 ssl;\n    listen [::]:443 ssl;\n    listen 443 quic reuseport;\n    listen [::]:443 quic reuseport;\n    http2 on;\n    server_name example.com www.example.com;\n\n    # Zertifikate von Certbot\n    ssl_certificate     \/etc\/letsencrypt\/live\/example.com\/fullchain.pem;\n    ssl_certificate_key \/etc\/letsencrypt\/live\/example.com\/privkey.pem;\n\n    # Wiederverwendbare Snippets\n    include \/etc\/nginx\/snippets\/tls-hardening.conf;\n    include \/etc\/nginx\/snippets\/security-headers.conf;\n\n    add_header Alt-Svc 'h3=\":443\"; ma=86400' always;\n\n    location \/ {\n        limit_req zone=general burst=20 nodelay;\n        limit_conn conn_limit 10;\n\n        proxy_pass http:\/\/backend_app;\n        proxy_http_version 1.1;\n        proxy_set_header Host              $host;\n        proxy_set_header X-Real-IP         $remote_addr;\n        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header Connection        \"\";\n\n        proxy_connect_timeout 5s;\n        proxy_read_timeout    60s;\n    }\n\n    location \/login {\n        limit_req zone=login burst=5 nodelay;\n        proxy_pass http:\/\/backend_app;\n        proxy_set_header Host            $host;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Speichern Sie die Datei, testen Sie mit <code>sudo nginx -t<\/code> und laden Sie mit <code>sudo systemctl reload nginx<\/code> neu. Diese Konfiguration ist ein solider Ausgangspunkt f\u00fcr die meisten Webanwendungen und l\u00e4sst sich modular um weitere <code>location<\/code>-Bl\u00f6cke oder zus\u00e4tzliche Domains erweitern.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"websockets-und-mehrere-backends-weiterleiten\">WebSockets und mehrere Backends weiterleiten<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"websocket-verbindungen-korrekt-durchreichen\">WebSocket-Verbindungen korrekt durchreichen<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Anwendungen mit Echtzeit-Funktionen (Chats, Live-Dashboards) nutzen WebSockets. Diese ben\u00f6tigen das HTTP-Upgrade-Protokoll, das Sie explizit durchreichen m\u00fcssen. Ohne die folgenden Header bricht die Verbindung sofort ab.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>location \/ws\/ {\n    proxy_pass http:\/\/backend_app;\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade    $http_upgrade;\n    proxy_set_header Connection \"upgrade\";\n    proxy_set_header Host       $host;\n    proxy_read_timeout 3600s;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"last-auf-mehrere-instanzen-verteilen\">Last auf mehrere Instanzen verteilen<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Skaliert Ihre Anwendung \u00fcber mehrere Prozesse oder Server, erweitern Sie den <code>upstream<\/code>-Block. Nginx verteilt die Last und nimmt ausgefallene Knoten automatisch aus der Rotation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>upstream backend_app {\n    least_conn;\n    server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;\n    server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;\n    server 10.0.0.5:3000  backup;\n    keepalive 32;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Direktive <code>least_conn<\/code> schickt neue Anfragen an die Instanz mit den wenigsten aktiven Verbindungen. Der mit <code>backup<\/code> markierte Server springt nur ein, wenn alle prim\u00e4ren Knoten ausfallen. So erreichen Sie Hochverf\u00fcgbarkeit ohne externen Load Balancer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fuenf-haeufige-fehler-und-wie-sie-sie-vermeiden\">F\u00fcnf h\u00e4ufige Fehler und wie Sie sie vermeiden<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. Fehlender Host-Header.<\/strong> Ohne <code>proxy_set_header Host $host;<\/code> sendet Nginx den Upstream-Namen statt der echten Domain. Anwendungen mit virtuellen Hosts oder absoluten Redirects liefern dann falsche URLs aus oder zeigen die falsche Seite. Setzen Sie den Host-Header in jedem <code>location<\/code>-Block, der weiterleitet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. Backend bindet an 0.0.0.0.<\/strong> Lauscht Ihre Anwendung auf allen Interfaces statt nur auf 127.0.0.1, ist sie unter Umst\u00e4nden direkt aus dem Internet erreichbar und umgeht den Reverse Proxy komplett. Binden Sie Backends immer an localhost und verlassen Sie sich nicht allein auf die Firewall.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>3. HSTS zu fr\u00fch aktiviert.<\/strong> Wer <code>Strict-Transport-Security<\/code> mit langer <code>max-age<\/code> setzt, bevor HTTPS stabil l\u00e4uft, sperrt Besucher aus. Der Browser merkt sich die Anweisung und verweigert HTTP, selbst wenn HTTPS sp\u00e4ter Probleme macht. Testen Sie HTTPS gr\u00fcndlich, bevor Sie HSTS scharf schalten, und beginnen Sie mit kurzer Laufzeit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>4. Vergessenes <code>nginx -t<\/code>.<\/strong> Ein <code>systemctl reload<\/code> mit fehlerhafter Konfiguration kann Nginx in einen inkonsistenten Zustand bringen. Pr\u00fcfen Sie jede \u00c4nderung erst mit <code>nginx -t<\/code>. Der Test findet Syntaxfehler, bevor sie produktiv werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>5. Zertifikatserneuerung ohne Reload.<\/strong> Erneuert Certbot das Zertifikat, l\u00e4dt Nginx es nicht automatisch. Ohne Deploy-Hook serviert der Server bis zum n\u00e4chsten Neustart das alte Zertifikat weiter, das eventuell schon abgelaufen ist. Konfigurieren Sie den Reload-Hook wie in Schritt 12 beschrieben.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"troubleshooting-die-haeufigsten-probleme-loesen\">Troubleshooting: Die h\u00e4ufigsten Probleme l\u00f6sen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Treten Probleme auf, liefert das Error-Log die entscheidenden Hinweise. Verfolgen Sie es live mit <code>sudo tail -f \/var\/log\/nginx\/error.log<\/code>. Die folgende Tabelle ordnet typische Symptome ihren Ursachen und L\u00f6sungen zu.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Symptom<\/th><th>Ursache<\/th><th>L\u00f6sung<\/th><\/tr><\/thead><tbody><tr><td>502 Bad Gateway<\/td><td>Backend nicht erreichbar oder abgest\u00fcrzt<\/td><td>Backend-Prozess pr\u00fcfen, Port und proxy_pass abgleichen<\/td><\/tr><tr><td>504 Gateway Timeout<\/td><td>Backend antwortet zu langsam<\/td><td>proxy_read_timeout erh\u00f6hen, Backend-Performance pr\u00fcfen<\/td><\/tr><tr><td>connection refused (upstream)<\/td><td>Backend lauscht auf anderem Port<\/td><td>Port im upstream-Block korrigieren<\/td><\/tr><tr><td>SSL-Handshake schl\u00e4gt fehl<\/td><td>Falscher Zertifikatspfad oder abgelaufen<\/td><td>Pfade pr\u00fcfen, certbot renew ausf\u00fchren<\/td><\/tr><tr><td>Certbot-Challenge schl\u00e4gt fehl<\/td><td>DNS zeigt nicht auf Server oder Port 80 zu<\/td><td>dig pr\u00fcfen, UFW Port 80 freigeben<\/td><\/tr><tr><td>Header erscheinen doppelt<\/td><td>add_header auf mehreren Ebenen<\/td><td>Header nur auf einer Ebene setzen<\/td><\/tr><tr><td>WebSocket bricht ab<\/td><td>Upgrade-Header fehlt<\/td><td>Upgrade- und Connection-Header setzen<\/td><\/tr><tr><td>Echte Client-IP fehlt im Log<\/td><td>X-Forwarded-For nicht ausgewertet<\/td><td>real_ip_module oder Backend-Auswertung konfigurieren<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Der Fehler 502 Bad Gateway ist mit Abstand der h\u00e4ufigste. Er bedeutet fast immer, dass das Backend nicht l\u00e4uft oder Nginx es unter der konfigurierten Adresse nicht findet. Pr\u00fcfen Sie mit <code>curl http:\/\/127.0.0.1:3000<\/code>, ob das Backend lokal antwortet, und vergleichen Sie den Port mit Ihrem <code>upstream<\/code>-Block. Bei TLS-Problemen liefert <code>openssl s_client -connect example.com:443 -servername example.com<\/code> die Details des Handshakes und des pr\u00e4sentierten Zertifikats.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fortgeschrittene-tipps-fuer-den-produktivbetrieb\">Fortgeschrittene Tipps f\u00fcr den Produktivbetrieb<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Gzip und Brotli f\u00fcr kleinere Antworten.<\/strong> Komprimieren Sie Textantworten, um Bandbreite zu sparen und Ladezeiten zu senken. Gzip ist \u00fcberall verf\u00fcgbar, Brotli komprimiert noch st\u00e4rker, ben\u00f6tigt aber das passende Modul.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gzip on;\ngzip_vary on;\ngzip_min_length 1024;\ngzip_types text\/plain text\/css application\/json application\/javascript text\/xml;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Proxy-Caching f\u00fcr statische Antworten.<\/strong> Cachen Sie Backend-Antworten, die sich selten \u00e4ndern, direkt im Proxy. Das entlastet das Backend drastisch und beschleunigt wiederholte Abrufe.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Im http-Block\nproxy_cache_path \/var\/cache\/nginx levels=1:2 keys_zone=app_cache:10m max_size=1g inactive=60m;\n\n# Im location-Block\nproxy_cache app_cache;\nproxy_cache_valid 200 10m;\nadd_header X-Cache-Status $upstream_cache_status;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Echte Client-IP korrekt protokollieren.<\/strong> Hinter einem weiteren Proxy oder CDN (etwa Cloudflare) m\u00fcssen Sie Nginx mitteilen, welchen Quell-IPs es vertrauen darf, damit <code>X-Forwarded-For<\/code> nicht gef\u00e4lscht werden kann. Konfigurieren Sie <code>set_real_ip_from<\/code> mit den vertrauensw\u00fcrdigen Netzbereichen und <code>real_ip_header X-Forwarded-For;<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Logging und Monitoring.<\/strong> Aktivieren Sie das Access-Log im JSON-Format f\u00fcr maschinelle Auswertung und \u00fcberwachen Sie 4xx- und 5xx-Raten. Ein pl\u00f6tzlicher Anstieg von 502-Fehlern weist auf ein abgest\u00fcrztes Backend hin, eine Welle von 429 oder 503 auf einen laufenden Brute-Force-Angriff, den Ihr Rate-Limiting abf\u00e4ngt. F\u00fcr ganzheitliche Server-Absicherung lohnt sich der Blick in unseren <a href=\"\/security-hub\/\">\u00dcberblick zur Online-Sicherheit<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"nginx-sicherheitsluecken-2025-und-2026-im-blick\">Nginx-Sicherheitsl\u00fccken 2025 und 2026 im Blick<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Reverse Proxy ist die exponierteste Komponente Ihrer Architektur, deshalb geh\u00f6ren Updates zur Pflicht. 2025 und 2026 wurden mehrere sicherheitsrelevante Fehler in Nginx behoben. Anfang 2025 etwa schloss das Projekt mit CVE-2025-23419 eine Schwachstelle bei der Wiederverwendung von TLS-Sitzungen, die in nginx 1.27.4 behoben wurde. Im Verlauf von 2025 und 2026 folgten weitere Fixes in den Bereichen TLS-Sitzungsbehandlung, HTTP\/2- und HTTP\/3-Verarbeitung sowie bei OCSP-Anfragen \u00fcber den Resolver.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die praktische Konsequenz ist einfach: Halten Sie Nginx aktuell, abonnieren Sie die Sicherheitsmeldungen des Projekts und spielen Sie Updates zeitnah ein. Auf Ubuntu liefern die Standard-Repositories Sicherheitspatches f\u00fcr den stabilen Zweig, mit <code>unattended-upgrades<\/code> automatisieren Sie das Einspielen. Reverse Proxies und Load Balancer sind ein beliebtes Angriffsziel, wie auch die schwere <a href=\"\/citrix-netscaler-luecke-2026\/\">Citrix-NetScaler-L\u00fccke 2026<\/a> gezeigt hat. Wer seine Konfiguration regelm\u00e4\u00dfig gegen den SSL Labs Test und das OWASP Secure Headers Project pr\u00fcft, schlie\u00dft die h\u00e4ufigsten Fehlerquellen aus. Die ma\u00dfgebliche Referenz f\u00fcr alle Direktiven bleibt die <a href=\"https:\/\/nginx.org\/en\/docs\/http\/configuring_https_servers.html\" target=\"_blank\" rel=\"noopener\">offizielle Nginx-HTTPS-Dokumentation<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fazit-ihr-gehaerteter-reverse-proxy\">Fazit: Ihr geh\u00e4rteter Reverse Proxy<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Sie haben in zw\u00f6lf Schritten einen vollwertigen <strong>Nginx Reverse Proxy<\/strong> aufgebaut: von der Installation \u00fcber die Backend-Anbindung, TLS-Terminierung mit Let&#8217;s Encrypt, geh\u00e4rtete Cipher Suites, Sicherheits-Header und Rate-Limiting bis zur automatischen Zertifikatserneuerung. Diese Konfiguration ist produktionsreif und folgt den Sicherheitsempfehlungen f\u00fcr 2026.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der n\u00e4chste sinnvolle Schritt ist Monitoring: Behalten Sie Fehlerraten, Zertifikatslaufzeiten und Antwortzeiten im Auge. Erweitern Sie die Konfiguration modular, wenn neue Dienste hinzukommen, und pr\u00fcfen Sie Ihre TLS-Konfiguration regelm\u00e4\u00dfig gegen aktuelle Empfehlungen. Ein gut gewarteter Reverse Proxy ist \u00fcber Jahre die verl\u00e4ssliche Eingangst\u00fcr zu Ihrer gesamten Infrastruktur.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"haeufig-gestellte-fragen-faq\">H\u00e4ufig gestellte Fragen (FAQ)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"was-ist-der-unterschied-zwischen-einem-reverse-proxy-und-einem-load-balancer\">Was ist der Unterschied zwischen einem Reverse Proxy und einem Load Balancer?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Reverse Proxy nimmt Anfragen entgegen und leitet sie an ein oder mehrere Backends weiter. Ein Load Balancer ist eine Spezialform, die Last gezielt auf mehrere Server verteilt. Nginx erf\u00fcllt beide Rollen: Mit einem einzelnen Backend ist es ein reiner Reverse Proxy, mit mehreren <code>server<\/code>-Eintr\u00e4gen im <code>upstream<\/code>-Block wird es zum Load Balancer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"brauche-ich-nginx-oder-reicht-caddy-oder-traefik\">Brauche ich Nginx oder reicht Caddy oder Traefik?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Caddy und Traefik holen Zertifikate automatisch und sind schneller eingerichtet. Nginx bietet daf\u00fcr mehr Kontrolle, h\u00f6here Performance unter Last und eine riesige Wissensbasis. F\u00fcr klassische Server-Setups und maximale Flexibilit\u00e4t ist Nginx weiterhin der Standard, f\u00fcr containerlastige Umgebungen kann Traefik bequemer sein.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wie-oft-erneuert-sich-das-lets-encrypt-zertifikat\">Wie oft erneuert sich das Let&#8217;s-Encrypt-Zertifikat?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Standard-Zertifikate sind 90 Tage g\u00fcltig. Der von Certbot installierte systemd-Timer pr\u00fcft zweimal t\u00e4glich und erneuert automatisch, sobald weniger als 30 Tage Restlaufzeit verbleiben. Mit korrekt gesetztem Deploy-Hook l\u00e4dt Nginx das neue Zertifikat ohne manuelles Eingreifen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"warum-bekomme-ich-einen-502-bad-gateway\">Warum bekomme ich einen 502 Bad Gateway?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Der h\u00e4ufigste Grund ist ein nicht laufendes Backend. Pr\u00fcfen Sie mit <code>curl http:\/\/127.0.0.1:3000<\/code>, ob Ihr Dienst antwortet, und vergleichen Sie den Port mit dem <code>upstream<\/code>-Block. Auch ein abgest\u00fcrzter Anwendungsprozess oder ein falscher <code>proxy_pass<\/code>-Eintrag l\u00f6sen diesen Fehler aus.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"sollte-ich-http-3-sofort-aktivieren\">Sollte ich HTTP\/3 sofort aktivieren?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">HTTP\/3 bringt sp\u00fcrbare Vorteile bei instabilen Verbindungen und mobilen Clients. Da es UDP-Port 443 ben\u00f6tigt und in manchen Netzwerken gefiltert wird, sollten Sie HTTP\/2 stets parallel aktiv lassen. So f\u00e4llt der Browser bei Bedarf zur\u00fcck. F\u00fcr die meisten Setups ist die Aktivierung beider Protokolle die beste Wahl.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wie-sichere-ich-den-reverse-proxy-zusaetzlich-ab\">Wie sichere ich den Reverse Proxy zus\u00e4tzlich ab?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Kombinieren Sie die Ma\u00dfnahmen aus dieser Anleitung mit fail2ban gegen wiederholte Angriffe, einer Web Application Firewall wie ModSecurity und regelm\u00e4\u00dfigen Updates. Beschr\u00e4nken Sie Admin-Bereiche per IP-Allowlist und nutzen Sie f\u00fcr den Serverzugang ausschlie\u00dflich SSH-Schl\u00fcssel statt Passw\u00f6rter.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"funktioniert-diese-anleitung-auch-auf-debian\">Funktioniert diese Anleitung auch auf Debian?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ja. Die Befehle sind nahezu identisch, da Ubuntu auf Debian basiert. Lediglich die Paketversionen k\u00f6nnen abweichen. UFW, Nginx und Certbot funktionieren auf aktuellen Debian-Releases genauso. Auf Rocky Linux oder AlmaLinux ersetzen Sie <code>apt<\/code> durch <code>dnf<\/code> und beachten die SELinux-Richtlinien.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"weiterfuehrende-artikel\">Weiterf\u00fchrende Artikel<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/https-und-tls\/\">HTTPS und TLS: Wie das Schloss im Browser Sie sch\u00fctzt<\/a><\/li>\n<li><a href=\"\/ssh-key-erstellen-ed25519\/\">SSH-Key erstellen: Ed25519 in 12 Schritten<\/a><\/li>\n<li><a href=\"\/pi-hole-unbound-einrichten\/\">Pi-hole + Unbound einrichten: 12 Schritte<\/a><\/li>\n<li><a href=\"\/opnsense-vs-pfsense\/\">OPNsense vs pfSense: EU vs USA, 0 \u20ac Basis<\/a><\/li>\n<li><a href=\"\/citrix-netscaler-luecke-2026\/\">Citrix NetScaler L\u00fccke: CVSS 9.3, KEV in 7 Tagen<\/a><\/li>\n<li><a href=\"\/security-hub\/\">Online-Sicherheit verst\u00e4ndlich erkl\u00e4rt<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Ein Nginx Reverse Proxy sitzt zwischen dem Internet und Ihren Backend-Anwendungen. Er nimmt jede Anfrage entgegen, beendet die TLS-Verschl\u00fcsselung, filtert Angriffe und reicht nur saubere Requests an Ihre Dienste weiter.\u2026<\/p>\n","protected":false},"author":7,"featured_media":129,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-128","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security"],"_links":{"self":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts\/128","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/comments?post=128"}],"version-history":[{"count":1,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts\/128\/revisions"}],"predecessor-version":[{"id":130,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts\/128\/revisions\/130"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/media\/129"}],"wp:attachment":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/media?parent=128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/categories?post=128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/tags?post=128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}