NGINX · TECH-STACK
Nginx als Reverse-Proxy: SSL, Rate-Limits und Security-Header für Container-Apps
Nginx 1.28 bedient als Edge-Layer Docker-Backends. Certbot-SSL, gzip/brotli, limit_req-Zonen, Cloudflare-IP-Allowlist, HSTS/CSP, Websocket-Upgrade.
Recherche & Faktencheck: DuneDive LLC · Stand: 2026-05
Was ist ein Nginx-Reverse-Proxy?
Ein Reverse-Proxy ist der erste Server, den ein Browser sieht, wenn er eine Domain aufruft. Er nimmt TLS-Verbindungen entgegen, prüft Anfragen, terminiert SSL, leitet den entschlüsselten Datenverkehr an interne Backend-Prozesse weiter und cached oder komprimiert die Antwort auf dem Rückweg. Nginx ist seit über 15 Jahren der De-facto-Standard für diese Rolle, weil er mit wenigen MB RAM tausende offene Verbindungen hält und seine Konfiguration deklarativ und gut dokumentiert ist.
Für einen Schweizer KMU-Betrieb mit Docker-Containern erfüllt Nginx genau die Aufgabe, die Cloudflare oder ein managed Load Balancer auf Cloud-Seite übernehmen würden – nur lokal und ohne monatliche Abogebühr. Mai 2026 ist Version 1.28 die Mainline; sie bringt natives HTTP/3 (QUIC), verbesserte OCSP-Stapling-Stabilität und ein neues `aio threads` für schnellere Datei-IO. Auf dem Fairlane-Hetzner-Server bedient eine einzige Nginx-Instanz 58 Sites – von statischen Marketing-Pages über Next.js-Apps bis zu n8n-Webhooks – alle mit Lets-Encrypt-Zertifikaten über Certbot, alle hinter Cloudflare-DNS.
Warum es zählt
Ohne Reverse-Proxy musste jeder Docker-Container selbst TLS-Zertifikate verwalten, Rate-Limits implementieren und Security-Header setzen – was kein Container-Image von Haus aus gut macht. Ein zentraler Edge-Layer löst das Problem an einer Stelle und entlastet die Anwendungs-Container.
Konkrete Effekte für einen KMU-Betrieb: Zertifikate werden zentral verwaltet (Certbot renewal alle 60 Tage, ein Cronjob). Rate-Limiting auf /api/login verhindert Brute-Force-Versuche auf jeden einzelnen Container automatisch. HTTP-zu-HTTPS-Redirect wird einmal definiert, nicht pro App. Statische Assets bekommen Cache-Control-Header, sodass Cloudflare oder der Browser sie effizient lagert. Bei Wartung kann ein Container auf 503 gestellt werden, ohne den Rest der Domain zu betreffen. Bei einem Audit nach revDSG lässt sich nachweisen, wo personenbezogene Daten den Perimeter verlassen – nämlich genau in der Nginx-Konfiguration, nicht verstreut in 25 Containern.
Wie es funktioniert
Eine produktionsreife Nginx-Konfiguration besteht aus drei Schichten: globale Server-Defaults, ein Server-Block pro Domain, und Location-Blöcke für Pfad-spezifisches Verhalten.
SSL-Terminierung mit Certbot. `certbot --nginx -d example.ch -d www.example.ch` legt das Zertifikat in /etc/letsencrypt/live/ ab und patcht den Server-Block. Ein systemd-Timer (oder Cronjob `0 3 * * *`) erneuert automatisch ab 30 Tagen Restlaufzeit. Wichtig: ssl_protocols TLSv1.2 TLSv1.3 – TLSv1.0 und TLSv1.1 raus, damit nach PCI-DSS und BSI-Empfehlung 2026 konform.
Gzip plus Brotli. Gzip ist out-of-the-box; Brotli kommt über das `libnginx-mod-http-brotli`-Paket. Brotli komprimiert HTML/JSON ca. 20% besser als Gzip; beide nebeneinander aktivieren – Nginx wählt anhand des `Accept-Encoding`-Headers.
Rate-Limiting per limit_req_zone. `limit_req_zone $binary_remote_addr zone=login:10m rate=5r/s;` definiert eine Zone. In der Location `/api/login` dann `limit_req zone=login burst=10 nodelay;`. Damit greift der Schutz spezifisch auf Login-Endpunkte, nicht pauschal – was statische Assets bremsen würde.
Cloudflare-IP-Allowlist plus Real-IP. Wenn Cloudflare als DNS-Proxy davor steht, sehen Backends nur Cloudflare-IPs. `set_real_ip_from <cloudflare-cidr>;` plus `real_ip_header CF-Connecting-IP;` stellt die Original-Besucher-IP wieder her. Ohne diesen Block sieht jedes Audit-Log nur 173.x.x.x – wertlos für Forensik. Die Cloudflare-CIDR-Liste ist statisch genug, um sie monatlich per Cron zu aktualisieren.
Security-Header. HSTS (`max-age=31536000; includeSubDomains; preload`), CSP angepasst pro App, X-Frame-Options DENY, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy restriktiv. Mozilla Observatory testet das in 30 Sekunden – Ziel A+.
Websocket-Upgrade. Für n8n, Grafana und Next.js-HMR braucht es `proxy_http_version 1.1;`, `proxy_set_header Upgrade $http_upgrade;`, `proxy_set_header Connection upgrade;`. Ohne diese drei Zeilen funktionieren Live-Updates nicht.
Nginx-Edge in 6 Schritten
- 01Nginx 1.28 plus libnginx-mod-http-brotli installieren (Mainline-Repo, nicht Distro-Default).
- 02Pro Domain ein /etc/nginx/sites-available/<domain>.conf, Symlink nach sites-enabled/. Niemals alles in nginx.conf.
- 03Certbot mit nginx-Plugin: certbot --nginx -d <domain>. Renewal-Cron prüfen.
- 04limit_req_zone in http{}-Block; limit_req in Login-/Upload-Locations. Burst und nodelay setzen.
- 05Cloudflare-CIDR + real_ip_header CF-Connecting-IP. Monthly cron aktualisiert die Liste.
- 06Security-Header in einem includebaren snippet (/etc/nginx/snippets/security.conf), in jedem Server-Block per include eingebunden. Mozilla Observatory prüfen.
Wann Nginx einsetzen
Nginx ist die richtige Wahl, wenn (a) mindestens ein Docker-Container per HTTPS öffentlich erreichbar sein soll, (b) mehrere Domains auf einem Host enden, oder (c) bestehende Apps ohne TLS-Support zugänglich gemacht werden sollen.
Konkrete Anwendungsfälle: Eine n8n-Instanz, die Webhooks aus Cobra-CRM oder Bexio entgegen nimmt – Nginx terminiert SSL und Cloudflare schützt vor DDoS. Eine Grafana-Instanz, die nur per IP-Allowlist im Büro erreichbar sein soll – `allow 192.0.2.0/24; deny all;` direkt im Location-Block. Eine Marketing-Site und ein RAG-Chat-Backend auf derselben Domain – `/` zu Next.js, `/api/chat` zu einem Python-Container.
Bei Fairlane bedient eine Nginx-Instanz 58 Sites mit etwa 240 Locations und produziert ca. 15 MB Logs pro Tag. RAM-Verbrauch unter 80 MB, CPU im einstelligen Prozent-Bereich. Das skaliert ohne Stress auf einem Server zwischen 64 und 128 GB RAM.
Wann NICHT
Nginx ist die falsche Wahl, wenn (a) ein managed Edge wie Cloudflare Tunnels oder Vercel bereits TLS plus CDN plus WAF abdeckt und der Host selbst nie direkt im Internet stehen muss, (b) ein hochfrequenter L4-Load-Balancer (Datenbanken, MQTT) gebraucht wird – dann ist HAProxy oder Envoy passender, oder (c) ein vollwertiger Application-Firewall mit Regex-basierten Angriffsregeln nötig ist – dafür ist ModSecurity plus OWASP CRS der richtige Stack, gerne aber als Modul vor Nginx.
Weitere Fallen: Nginx als Tomcat-Ersatz für Java-Servlets zu verwenden, indem man `proxy_pass` an irgendwelche internen JBoss-Ports leitet, ohne Session-Affinity zu testen. CSP-Header copy-paste aus Internet-Tutorials ohne CSP-Report-Only-Phase – die App ist dann sofort kaputt. Und: `client_max_body_size 0;` bedeutet unbegrenzt, was bei einem öffentlichen Upload-Endpunkt ein Open-Door für Disk-Füller-Angriffe ist.
Vor- und Nachteile
STÄRKEN
- Eine Konfigurationsdatei pro Domain, in Git versionierbar
- TLS und Rate-Limiting zentral, nicht pro App
- Niedriger Ressourcen-Verbrauch – 80 MB RAM für 58 Sites
- 15 Jahre Doku, jede Frage hat eine Antwort im Netz
SCHWÄCHEN
- Keine Auto-Discovery – neue Container brauchen manuelle Conf-Datei
- CSP und Security-Header sind nicht trivial korrekt zu setzen
- Reload-Fehler killen die ganze Nginx-Instanz: nginx -t vor jedem reload Pflicht
- OpenResty/Lua-Module verlocken zu zu viel Custom-Logik im Edge-Layer
Häufige Fragen
Wozu nginx, wenn Cloudflare schon TLS terminiert?
Cloudflare terminiert TLS zum Browser, aber die Verbindung zum Origin-Server muss eigene TLS haben – sonst lauert ein Klartext-Hop zwischen Cloudflare und Hetzner über das öffentliche Internet. Nginx mit gültigem Origin-Cert (Lets-Encrypt oder Cloudflare-Origin-Cert) schliesst diese Lücke. Zusätzlich routet Nginx vor Ort zwischen mehreren Backend-Containern – das macht Cloudflare nicht.
Sollte ich Caddy oder Traefik statt Nginx einsetzen?
Caddy ist die einfachste Wahl für ein bis fünf Domains mit Auto-SSL ohne Certbot. Traefik integriert sich direkt in Docker-Labels und konfiguriert sich selbst beim Container-Start. Beide sind solide. Nginx gewinnt bei vielen Domains (>20), feinkörnigem Rate-Limiting, vielen Custom-Locations und langer Doku-Halbwertszeit. Bei Fairlane mit 58 Sites schlägt Nginx auf Performance und Doku-Verfügbarkeit.
Wie debugge ich 502 Bad Gateway?
Drei Ursachen in 95% der Fälle: (1) Backend-Container nicht erreichbar – `docker ps` zeigt, ob der Container läuft und welcher Port veröffentlicht ist. (2) Falsche proxy_pass-URL – Container-Name plus Container-Port, nicht Host-Port. (3) Timeout – `proxy_read_timeout 60s;` reicht für normale Apps, für LLM-Calls auf 300s erhöhen. error.log in /var/log/nginx/ liefert die genaue Zeile.
Verwandte Themen
Quellen
PASSEND ZU IHREM STACK?