Nginx Reverse Proxy — drei Wörter, die in jedem modernen Server-Setup auftauchen, und zwar aus gutem Grund. Egal ob du eine Node.js-App betreibst, einen Docker-Container, eine Python-API oder eine komplette Microservices-Architektur: Die Chancen stehen gut, dass du etwas vor deiner Anwendung brauchst, das SSL handhabt, Traffic verteilt, Antworten cachet und dein Backend vor dem öffentlichen Internet versteckt. Dieses Etwas ist fast immer Nginx.
Wir betreiben Nginx als Reverse Proxy seit Jahren in der Produktion — vor Shopware-Shops, Next.js-Apps, API-Gateways und containerisierten Services. Dieser Guide ist nicht die Nginx-Dokumentation in freundlicherem Deutsch umgeschrieben. Es ist das praktische Wissen aus hunderten echter Deployments, inklusive der Fehler die uns nachts um 2 Uhr Stunden gekostet haben und der Konfigurationen die tatsächlich Traffic-Spikes überlebt haben.
Am Ende dieses Artikels wirst du genau verstehen, wie Nginx als Reverse Proxy funktioniert, wie du es von Grund auf einrichtest und wie du es für die Produktion mit SSL, Load Balancing, Caching, WebSocket-Support und Security Hardening konfigurierst.
Ist Nginx ein Reverse Proxy?
Ja — und einer der besten dafür. Obwohl Nginx ursprünglich als Webserver entwickelt wurde, um das C10K-Problem zu lösen (10.000 gleichzeitige Verbindungen), wurden seine Reverse-Proxy-Fähigkeiten schnell zum beliebtesten Feature. Heute nutzt ein erheblicher Teil der Nginx-Installationen weltweit den Server primär oder ausschließlich als Reverse Proxy, nicht als klassischen Webserver der Dateien von der Festplatte ausliefert.
Die wichtige Unterscheidung: Nginx ist nicht nur ein Reverse Proxy. Es ist ein Webserver, ein Reverse Proxy, ein Load Balancer, ein Mail-Proxy und ein HTTP-Cache — alles in einer einzigen Binary. Aber seine event-gesteuerte, nicht-blockierende Architektur macht es besonders gut in der Reverse-Proxy-Rolle, weil Proxying im Kern effizientes Verbindungsmanagement ist — und genau dafür wurde Nginx gebaut.
Was ist ein Reverse Proxy und wie funktioniert Nginx dabei?
Ein Reverse Proxy sitzt zwischen Clients (Browsern, mobilen Apps, API-Konsumenten) und deinen Backend-Servern. Statt dass Clients sich direkt mit deiner Anwendung verbinden, verbinden sie sich mit dem Reverse Proxy, der die Anfrage dann an das passende Backend weiterleitet, die Antwort empfängt und an den Client zurückschickt.
Warum „Reverse”? Ein normaler (Forward) Proxy sitzt vor den Clients und leitet deren Anfragen nach außen weiter — denk an Firmen-Firewalls oder VPNs. Ein Reverse Proxy macht das Gegenteil: Er sitzt vor den Servern und nimmt eingehende Anfragen in deren Namen entgegen.

Was Nginx als Reverse Proxy macht:
- Empfängt alle eingehenden HTTP/HTTPS-Anfragen auf Port 80 und 443
- Terminiert SSL/TLS, damit deine Backend-Anwendungen keine Zertifikate verwalten müssen
- Routet Anfragen ans richtige Backend basierend auf Domainname, URL-Pfad, Headers oder anderen Kriterien
- Verteilt Last (Load Balancing) über mehrere Backend-Instanzen
- Cachet Antworten um die Backend-Last zu reduzieren
- Komprimiert Antworten (gzip/brotli) bevor sie an Clients gesendet werden
- Puffert Anfragen und Antworten, um langsame Backends vor langsamen Clients zu schützen
- Fügt Security-Header hinzu, Rate Limiting und Zugriffskontrollen
- Versteckt deine Backend-Infrastruktur vor dem öffentlichen Internet
Die Schönheit dieser Architektur: Deine Backend-Anwendungen können sich rein auf die Business-Logik konzentrieren. Sie lauschen auf localhost, sie kümmern sich nicht um SSL, sie machen sich keine Sorgen über langsame Clients die Verbindungen offen halten. Nginx erledigt all das.
Wie Nginx als Reverse Proxy funktioniert: Die Architektur
Das Verständnis der Interna hilft dir, Nginx richtig zu konfigurieren und Probleme zu debuggen wenn sie auftreten.
Event-gesteuerte, nicht-blockierende I/O
Traditionelle Webserver wie Apache (in seinem Standard-Prefork-Modus) starten einen Prozess oder Thread für jede Verbindung. Das funktioniert bei niedriger Last, wird aber teuer wenn du tausende gleichzeitige Verbindungen hast — jeder Prozess verbraucht Speicher, selbst während er auf I/O wartet.
Nginx geht einen fundamental anderen Weg. Es verwendet eine event-gesteuerte Architektur mit einer kleinen Anzahl Worker-Prozesse (typischerweise einer pro CPU-Kern). Jeder Worker nutzt nicht-blockierende I/O und einen Event-Loop (epoll unter Linux, kqueue unter BSD) um tausende Verbindungen gleichzeitig innerhalb eines einzigen Prozesses zu bedienen.
Für Reverse Proxying ist das perfekt. Die meiste Zeit eines Proxys wird mit Warten verbracht — auf die Client-Anfrage warten, auf die Backend-Antwort warten, auf die Client-Bestätigung warten. Nginx kann all dieses Warten effizient über tausende Verbindungen multiplexen, ohne Ressourcen zu verschwenden.
Der Request-Flow
Wenn eine Anfrage bei Nginx als Reverse Proxy ankommt, passiert Folgendes:
- Verbindung angenommen — der Worker-Prozess nimmt die Client-Verbindung über den Event-Loop an
- Request geparst — Nginx liest und parst die HTTP-Request-Header
- Server-Block zugeordnet — basierend auf dem
Host-Header und derlisten-Direktive wählt Nginx den richtigenserver-Block - Location zugeordnet — der URL-Pfad wird gegen
location-Blöcke abgeglichen - Upstream-Verbindung — Nginx öffnet (oder wiederverwendet) eine Verbindung zum Backend-Server
- Request weitergeleitet — die Client-Anfrage wird ans Backend gesendet, ggf. mit modifizierten Headern
- Antwort empfangen — die Backend-Antwort wird gelesen (und optional gepuffert/gecachet)
- Antwort gesendet — die Antwort wird an den Client zurückgeschickt
- Logging — der Request wird gemäß dem konfigurierten Log-Format protokolliert
Der gesamte Flow ist nicht-blockierend. Wenn das Backend langsam ist, blockiert Nginx keinen Thread — es bedient einfach andere Verbindungen und kommt zurück wenn das Backend Daten bereit hat.
Schritt für Schritt: Nginx als Reverse Proxy einrichten
Lass uns von einem frischen Linux-Server zu einem funktionierenden Reverse Proxy kommen. Wir verwenden Ubuntu/Debian-Befehle, aber die Nginx-Konfiguration selbst ist distributionsübergreifend identisch.
Schritt 1: Nginx installieren
sudo apt update
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
Prüfe ob es läuft:
curl -I http://localhost
# Sollte HTTP/1.1 200 OK zurückgeben
Schritt 2: Grundlegende Reverse-Proxy-Konfiguration
Nehmen wir an, du hast eine Node.js-Anwendung auf Port 3000 laufen. Hier ist die einfachste mögliche Reverse-Proxy-Konfiguration:
# /etc/nginx/sites-available/myapp
server {
listen 80;
server_name myapp.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Aktivieren:
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t # Konfiguration testen
sudo systemctl reload nginx

Die vier essentiellen Proxy-Header erklärt:
Host $host— gibt den ursprünglichen Domainnamen ans Backend weiter (kritisch für Virtual Hosting)X-Real-IP $remote_addr— teilt dem Backend die echte Client-IP mit, nicht die IP von NginxX-Forwarded-For $proxy_add_x_forwarded_for— hängt die Client-IP an die Forwarding-Kette an (wichtig bei mehreren Proxies)X-Forwarded-Proto $scheme— teilt dem Backend mit, ob die ursprüngliche Anfrage HTTP oder HTTPS war (kritisch für Redirect-URLs und Cookie-Sicherheit)
Ohne diese Header sieht dein Backend jede Anfrage als von 127.0.0.1 über Plain HTTP kommend. Das bricht Logging, Rate Limiting, Session-Management und die Hälfte deiner Anwendungslogik.
Schritt 3: SSL/TLS-Terminierung mit Let’s Encrypt
Der häufigste Grund Nginx als Reverse Proxy zu nutzen ist SSL-Terminierung. Dein Backend spricht Plain HTTP auf localhost, Nginx übernimmt die gesamte HTTPS-Komplexität.
# Certbot installieren
sudo apt install certbot python3-certbot-nginx -y
# Zertifikat holen (Nginx-Plugin macht alles automatisch)
sudo certbot --nginx -d myapp.example.com
Certbot modifiziert deine Nginx-Config automatisch. Das Ergebnis sieht so aus:
server {
listen 443 ssl http2;
server_name myapp.example.com;
ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name myapp.example.com;
return 301 https://$host$request_uri;
}
Produktions-SSL-Tipps die wir auf die harte Tour gelernt haben:
- Immer
ssl_session_cacheeinbauen — ohne macht jede Verbindung einen vollen TLS-Handshake, das ist teuer - Nur
TLSv1.2 TLSv1.3nutzen — TLS 1.0 und 1.1 sind deprecated und unsicher - Einen Cron für
certbot reneweinrichten (Certbot macht das normalerweise automatisch, aber mitsudo certbot renew --dry-runüberprüfen)
Schritt 4: Mehrere Backend-Services
Reale Setups haben selten nur ein Backend. So proxyierst du mehrere Services auf derselben Domain:
server {
listen 443 ssl http2;
server_name example.com;
# Frontend (Next.js auf Port 3000)
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# API (Express auf Port 4000)
location /api/ {
proxy_pass http://127.0.0.1:4000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Admin-Panel (separater Service auf Port 9000)
location /admin/ {
proxy_pass http://127.0.0.1:9000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Achtung: der Trailing Slash bei proxy_pass! Das ist einer der häufigsten Nginx-Fehler:
proxy_pass http://127.0.0.1:9000;— gibt die volle URI inklusive/admin/ans Backend weiterproxy_pass http://127.0.0.1:9000/;— entfernt/admin/und gibt nur den Rest weiter
Wenn dein Admin-Panel intern Requests auf / erwartet, brauchst du den Trailing Slash. Wenn es /admin/ erwartet, nicht. Das falsch zu machen verursacht mysteriöse 404-Fehler.
Load Balancing mit Nginx Reverse Proxy
Wenn ein einzelner Backend-Server nicht ausreicht, kann Nginx Traffic auf mehrere Instanzen verteilen.

Grundlegendes Load Balancing
upstream myapp_backend {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
server {
listen 443 ssl http2;
server_name myapp.example.com;
location / {
proxy_pass http://myapp_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Standardmäßig nutzt Nginx Round-Robin — Anfragen werden gleichmäßig auf alle Server verteilt. Aber es gibt bessere Optionen:
Load-Balancing-Algorithmen
upstream myapp_backend {
# Least Connections — sendet an den Server mit den wenigsten aktiven Verbindungen
least_conn;
server 127.0.0.1:3001 weight=3; # Bekommt 3x mehr Traffic
server 127.0.0.1:3002 weight=1;
server 127.0.0.1:3003 weight=1 backup; # Nur genutzt wenn die anderen down sind
}
upstream myapp_backend {
# IP Hash — selber Client geht immer zum selben Server (Sticky Sessions)
ip_hash;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
Unsere Empfehlung: Nutze least_conn für API-Backends (verteilt Last am gleichmäßigsten) und ip_hash nur wenn deine Anwendung Sticky Sessions braucht (was sie idealerweise nicht sollte — zustandslose Backends skalieren besser).
Health Checks
Nginx markiert einen Server automatisch als nicht verfügbar wenn er nicht antwortet:
upstream myapp_backend {
server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3002 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3003 max_fails=3 fail_timeout=30s backup;
}
Nach 3 fehlgeschlagenen Requests stoppt Nginx den Traffic zu diesem Server für 30 Sekunden und versucht es dann erneut. Einfach aber effektiv.
WebSocket-Support
WebSockets brauchen spezielle Behandlung weil sie die HTTP-Verbindung zu einem persistenten, bidirektionalen Kanal upgraden. Ohne richtige Konfiguration werden WebSocket-Verbindungen durch deinen Nginx Reverse Proxy fehlschlagen.
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400s; # WebSocket 24h am Leben halten
proxy_send_timeout 86400s;
}
Die drei kritischen Zeilen:
proxy_http_version 1.1— WebSockets benötigen HTTP/1.1 (HTTP/1.0 unterstützt den Upgrade-Mechanismus nicht)proxy_set_header Upgrade $http_upgrade— gibt den Upgrade-Header vom Client weiterproxy_set_header Connection "upgrade"— sagt dem Backend, dass es das Protokoll wechseln soll
Ohne proxy_read_timeout schließt Nginx inaktive WebSocket-Verbindungen nach 60 Sekunden (dem Standard). Setze es auf etwas das lang genug für deinen Anwendungsfall ist.
Caching: Den Reverse Proxy schnell machen
Eines der mächtigsten Features von Nginx als Reverse Proxy ist Response-Caching. Statt jede Anfrage ans Backend weiterzuleiten, kann Nginx gecachte Antworten direkt ausliefern — das reduziert die Backend-Last und verbessert die Antwortzeiten dramatisch.
Grundlegendes Proxy-Cache-Setup
# Im http {}-Block (nginx.conf)
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m
max_size=1g inactive=60m use_temp_path=off;
# Im server {} oder location {}-Block
location / {
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://127.0.0.1:3000;
}
Wichtige Direktiven erklärt:
proxy_cache_valid 200 302 10m— erfolgreiche Antworten für 10 Minuten cachenproxy_cache_use_stale— veralteten gecachten Inhalt ausliefern wenn das Backend down ist (das ist ein Lebensretter in der Produktion)proxy_cache_lock on— wenn mehrere Anfragen gleichzeitig dieselbe ungecachte URL treffen, geht nur eine ans Backend; der Rest wartet bis der Cache gefüllt istX-Cache-Status-Header — damit kannst du verifizieren dass Caching funktioniert (Werte: HIT, MISS, BYPASS, EXPIRED, STALE)
Selektives Caching
Nicht alles sollte gecachet werden. Dynamischer, benutzerspezifischer Inhalt muss den Cache umgehen:
location / {
proxy_cache my_cache;
# Requests mit Cookies nicht cachen (wahrscheinlich authentifiziert)
proxy_cache_bypass $http_cookie;
proxy_no_cache $http_cookie;
# POST-Requests nicht cachen
proxy_cache_methods GET HEAD;
proxy_pass http://127.0.0.1:3000;
}
# API-Endpoints — kein Caching
location /api/ {
proxy_pass http://127.0.0.1:4000;
proxy_no_cache 1;
proxy_cache_bypass 1;
}
Security Hardening für deinen Nginx Reverse Proxy
Ein Reverse Proxy ist deine erste Verteidigungslinie. Hier sind die Security-Konfigurationen die wir bei jedem Produktions-Deployment nutzen:

Security-Header
# Im server {}-Block hinzufügen
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
Rate Limiting
Schütze dein Backend vor Missbrauch:
# Im http {}-Block
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
# In location {}-Blöcken
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://127.0.0.1:4000;
}
location /auth/login {
limit_req zone=login_limit burst=5;
proxy_pass http://127.0.0.1:4000;
}
Request-Größenlimits
Verhindere dass überdimensionierte Uploads dein Backend crashen:
client_max_body_size 10m; # Maximale Upload-Größe
client_body_buffer_size 128k; # Puffer für Request-Bodies
proxy_buffer_size 4k; # Puffer für Response-Header
proxy_buffers 4 32k; # Puffer für den Response-Body
proxy_busy_buffers_size 64k;
Backend-Informationen verstecken
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
server_tokens off;
Performance-Tuning
Diese Optimierungen machen unter echtem Traffic einen messbaren Unterschied:
Connection Keepalive zum Backend
Standardmäßig öffnet Nginx für jeden Request eine neue Verbindung zum Backend. Bei hohem Traffic ist das verschwenderisch:
upstream myapp_backend {
server 127.0.0.1:3000;
keepalive 32; # 32 idle Verbindungen pro Worker offen halten
}
location / {
proxy_pass http://myapp_backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # Erforderlich für Keepalive zum Upstream
}
Gzip-Komprimierung
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml application/xml+rss text/javascript
image/svg+xml;
Timeouts (sinnvolle Standardwerte)
proxy_connect_timeout 5s; # Zeit für Verbindungsaufbau zum Backend
proxy_send_timeout 60s; # Zeit zum Senden der Anfrage ans Backend
proxy_read_timeout 60s; # Zeit zum Lesen der Antwort vom Backend
send_timeout 60s; # Zeit zum Senden der Antwort an den Client
Timeouts nicht zu hoch setzen. Ein 300-Sekunden proxy_read_timeout bedeutet, dass ein festsitzendes Backend Client-Verbindungen fünf Minuten blockiert. Für die meisten APIs sind 30-60 Sekunden vernünftig. Langlebige Operationen sollten stattdessen WebSockets oder Polling nutzen.
Docker- und Container-Setups
In containerisierten Umgebungen sehen Nginx Reverse Proxy-Konfigurationen leicht anders aus:
Docker Compose Beispiel
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./certs:/etc/nginx/certs
depends_on:
- app
networks:
- webnet
app:
build: .
expose:
- "3000" # Nicht zum Host veröffentlicht — nur im Docker-Netzwerk erreichbar
networks:
- webnet
networks:
webnet:
In der Nginx-Config nutzt du den Service-Namen als Upstream:
upstream app {
server app:3000; # Docker-DNS löst den Service-Namen auf
}
server {
listen 80;
location / {
proxy_pass http://app;
}
}
Wichtig für Docker: Der Backend-Port nutzt expose, nicht ports. Mit ports: "3000:3000" ist das Backend auch direkt aus dem Internet erreichbar, am Reverse Proxy vorbei. Mit expose können nur Container im selben Docker-Netzwerk darauf zugreifen.
Nginx vs Caddy vs Traefik: Wann nimmt man was?
Nginx ist nicht die einzige Reverse-Proxy-Option in 2026. Hier ein ehrlicher Vergleich:
| Feature | Nginx | Caddy | Traefik |
|---|---|---|---|
| Automatisches HTTPS | Nein (braucht Certbot) | Ja (eingebaut) | Ja (eingebaut) |
| Config-Format | Custom Syntax | Caddyfile (einfach) | YAML/TOML/Labels |
| Docker-Integration | Manuell | Gut | Exzellent |
| Performance | Exzellent | Sehr gut | Gut |
| Lernkurve | Moderat | Niedrig | Moderat |
| Community/Ökosystem | Riesig | Wachsend | Groß |
| Produktions-Track Record | Jahrzehnte | Jahre | Jahre |
Unsere Einschätzung: Für einfache Setups mit automatischem HTTPS ist Caddy ehrlich einfacher. Für Docker/Kubernetes mit dynamischer Service-Discovery glänzt Traefik. Für alles andere — hoher Traffic, komplexes Routing, maximale Performance, Custom-Module — bleibt Nginx der Standard. Wir nutzen tatsächlich Caddy für einige unserer eigenen Projekte, aber Nginx ist immer noch das was wir bei wichtigen Deployments einsetzen.
Troubleshooting: Häufige Nginx-Reverse-Proxy-Probleme
502 Bad Gateway
Der häufigste Fehler. Er bedeutet dass Nginx das Backend nicht erreichen kann.
Prüfe:
- Läuft das Backend überhaupt?
curl http://127.0.0.1:3000 - Ist der Port in deinem
proxy_passkorrekt? - Gibt es Firewall-Regeln die Localhost-Verbindungen blockieren?
- Prüfe
sudo tail -f /var/log/nginx/error.log
504 Gateway Timeout
Nginx hat sich mit dem Backend verbunden, aber das Backend hat zu lange für die Antwort gebraucht.
Fix: proxy_read_timeout erhöhen — aber auch das langsame Backend reparieren:
location /langsamer-endpoint {
proxy_read_timeout 120s;
proxy_pass http://127.0.0.1:3000;
}
Mixed Content / Redirect-Loops
Normalerweise verursacht durch fehlenden X-Forwarded-Proto-Header. Dein Backend generiert HTTP-URLs weil es nicht weiß, dass die Original-Anfrage HTTPS war.
Fix: Stelle sicher dass proxy_set_header X-Forwarded-Proto $scheme; gesetzt ist UND dein Backend-Framework so konfiguriert ist dass es Proxy-Headern vertraut.
413 Request Entity Too Large
Der Upload ist größer als client_max_body_size (Standard 1MB).
Fix: client_max_body_size 50m; im relevanten Server- oder Location-Block.
WebSocket-Verbindung bricht nach 60 Sekunden ab
Standard-proxy_read_timeout ist 60 Sekunden. Inaktive WebSocket-Verbindungen werden gekillt.
Fix: proxy_read_timeout auf die gewünschte Verbindungsdauer erhöhen.
Komplettes Produktions-Konfigurations-Template
Hier ist eine vollständige, produktionsreife Nginx Reverse Proxy-Konfiguration die wir tatsächlich nutzen:
# /etc/nginx/sites-available/production-app
upstream app_backend {
least_conn;
server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3002 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name app.example.com;
# SSL
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Security-Header
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Logging
access_log /var/log/nginx/app-access.log;
error_log /var/log/nginx/app-error.log;
# Limits
client_max_body_size 25m;
server_tokens off;
# Komprimierung
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml text/javascript image/svg+xml;
# Hauptanwendung
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# WebSocket-Endpoint
location /ws {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400s;
}
# Statische Assets — direkt ausliefern, Proxy umgehen
location /static/ {
alias /var/www/app/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Häufig gestellte Fragen
Ist Nginx ein Reverse Proxy?
Ja, und einer der weltweit am häufigsten eingesetzten. Seine event-gesteuerte Architektur macht es außergewöhnlich effizient bei der Verwaltung tausender gleichzeitiger Proxy-Verbindungen. Du konfigurierst es mit der proxy_pass-Direktive in einem location-Block, und es übernimmt das Weiterleiten von Anfragen, Verbindungsmanagement und Zurücksenden von Antworten.
Was ist ein Nginx Reverse Proxy?
Ein Nginx Reverse Proxy ist eine Nginx-Instanz, die zwischen Clients und deinen Backend-Servern sitzt. Er nimmt eingehende Anfragen entgegen und leitet sie an die richtigen Backend-Server weiter. Er kann dabei SSL terminieren, Load Balancing durchführen, Antworten cachen und Security-Header hinzufügen — alles transparent für den Client.
Kann Nginx als Reverse Proxy fungieren?
Absolut. Das ist sogar einer der Hauptanwendungsfälle von Nginx. Die Konfiguration ist unkompliziert: Du brauchst einen server-Block mit der proxy_pass-Direktive und den richtigen Proxy-Headern. Nginx wurde von Grund auf für effizientes Verbindungsmanagement gebaut, was es zum idealen Reverse Proxy macht.
Wie funktioniert Nginx als Reverse Proxy?
Nginx akzeptiert eingehende Client-Verbindungen und leitet sie basierend auf deinen Konfigurationsregeln an Backend-Server weiter. Es nutzt nicht-blockierende I/O um viele Verbindungen mit minimalem Ressourcenverbrauch zu verwalten. Der Client kommuniziert nie direkt mit deinem Backend — Nginx agiert als Vermittler der SSL hinzufügen, Header modifizieren, Antworten cachen und Last über mehrere Server verteilen kann.
Ist Nginx besser als Apache als Reverse Proxy?
Für die Reverse-Proxy-Rolle speziell: ja. Nginxs event-gesteuerte Architektur behandelt gleichzeitige Verbindungen effizienter als Apaches prozessbasiertes Modell. Es verbraucht weniger Speicher unter Last und kann mehr simultane Verbindungen bewältigen. Apache kann als Reverse Proxy mit mod_proxy funktionieren, aber Nginx wurde für diesen Anwendungsfall von Grund auf konzipiert.
Kann ich Nginx Reverse Proxy mit Docker nutzen?
Ja, und es ist eins der häufigsten Setups. Du kannst Nginx als Docker-Container betreiben und Dockers internes DNS nutzen um Service-Namen als Upstream-Server aufzulösen. Alternativ kannst du Nginx auf dem Host laufen lassen und zu Containern über ihre veröffentlichten Ports proxyen. Für dynamische Container-Umgebungen ist Traefik mit seiner eingebauten Docker-Integration eine Überlegung wert.
Fazit: Nginx Reverse Proxy ist das Fundament
Nginx als Reverse Proxy ist nicht glamourös. Es ist nicht der Teil deines Stacks der in Blogposts erwähnt wird oder Investoren beeindruckt. Aber es ist das Fundament auf dem alles andere sitzt — die Schicht die SSL handhabt damit deine App es nicht muss, die Last verteilt damit ein Server-Crash deinen Service nicht lahmlegt, die Antworten cachet damit deine Datenbank nicht überlastet wird, und die einen zentralen Punkt für Security-Policies bietet.
Die Konfigurationen die wir in diesem Guide behandelt haben — grundlegendes Proxying, SSL-Terminierung, Load Balancing, WebSocket-Support, Caching und Security Hardening — decken 95 Prozent aller realen Nginx Reverse Proxy-Deployments ab. Die restlichen 5 Prozent betreffen spezialisierte Module und Randfälle, die die Nginx-Dokumentation gut abdeckt sobald du die Grundlagen verstehst.
Unsere praktische Empfehlung: Starte mit der einfachsten möglichen Konfiguration (Schritt 2 oben), füge SSL hinzu (Schritt 3), dann schichte Caching, Load Balancing und Security Hardening drauf wenn deine Anforderungen wachsen. Überingenieure dein erstes Setup nicht — eine funktionierende einfache Config schlägt eine kaputte komplexe Config jedes einzelne Mal.