Nginx als Reverse Proxy einrichten
Ein Reverse Proxy ist ein Server, der zwischen den Besuchern und Ihrer Anwendung steht: Er nimmt die Anfrage aus dem Internet entgegen, leitet sie an die Anwendung dahinter weiter und schickt deren Antwort an den Besucher zurück. Der Besucher sieht nur den Reverse Proxy und weiß nicht, auf welchem Port oder in welcher Sprache die Anwendung läuft.
Anwendungen in Node.js, Python, Java, .NET oder Go laufen meist mit einem eigenen kleinen Webserver auf einem Port wie 3000 oder 8080. Statt eine solche Anwendung direkt ins Internet zu stellen, setzt man Nginx davor: So lassen sich mehrere Anwendungen unter einer Adresse anbieten, HTTPS an einer Stelle verwalten, statische Dateien schnell ausliefern und Grenzen wie Anfragegröße und Zeitüberschreitung (Timeout) zentral festlegen. Das Konzept selbst erklärt die Anleitung Was ist ein Reverse Proxy?.
Diese Anleitung baut Schritt für Schritt eine funktionierende Konfiguration für einen einzelnen Backend-Server auf. In den Beispielen lautet die Domain beispiel.de und die Adresse der Anwendung 127.0.0.1:3000.
Kurz gefasst
- Nginx nimmt die Anfrage entgegen und leitet sie mit proxy_pass an die Anwendung dahinter weiter.
- Ein Schrägstrich am Ende von proxy_pass verändert den Pfad, der an das Backend geht.
- Ohne Host- und X-Forwarded-*-Header sieht die Anwendung weder die echte IP noch https.
- Nach jeder Änderung mit nginx -t testen, dann neu laden.
Das brauchen Sie
- Ein Server mit installiertem Nginx und Administratorrechte (sudo)
- Eine auf dem Server laufende Anwendung und der Port, auf dem sie lauscht (im Beispiel 127.0.0.1:3000)
- Eine Domain, die auf die IP-Adresse des Servers zeigt
- Eine SSH-Sitzung, in der Sie die Konfigurationsdateien bearbeiten können
Hinweis
Die Beispiele zeigen nur Port 80 (HTTP). Eine produktive Website braucht zusätzlich HTTPS; Zertifikat und die Einstellungen für Port 443 behandelt eine eigene Anleitung.
Auf dieser Seite
Einrichtung Schritt für Schritt
-
Die Anwendung nur auf der lokalen Adresse lauschen lassen
Laufen Nginx und die Anwendung auf demselben Server, sollte die Anwendung auf
127.0.0.1statt auf0.0.0.0(alle Netzwerkschnittstellen) lauschen. Dann erreicht sie nur der Nginx auf demselben Server; niemand kann Nginx umgehen und sich direkt mithttp://server-ip:3000verbinden.Läuft die Anwendung auf einem anderen Server, binden Sie sie an die interne Netzwerkadresse (z. B.
10.0.0.5) und erlauben Sie in der Firewall nur dem Nginx-Server den Zugriff auf diesen Port. Dieser Schritt ist auch die Voraussetzung dafür, dass die später beschriebene Einstellung zur „echten IP“ sicher ist.
: Vergrößern -
Den server-Block anlegen
In Nginx wird jede Website durch einen
server-Block definiert. Legen Sie eine neue Konfigurationsdatei an. Der Ort hängt von der Distribution ab:.conf-Dateien unter/etc/nginx/conf.d/sind eine verbreitete Struktur; Debian und Ubuntu verwenden/etc/nginx/sites-available/zusammen mitsites-enabled/.Nginx# Beispieldatei: /etc/nginx/conf.d/beispiel.de.conf (Pfad je nach Distribution) server { listen 80; server_name beispiel.de www.beispiel.de; location / { # Alle Anfragen an die Anwendung hinter Nginx weiterleiten proxy_pass http://127.0.0.1:3000; } }listenlegt den Port fest, auf dem gelauscht wird,server_namedie Domainnamen, für die dieser Block antwortet. Der Blocklocation /umfasst alle Adressen; die Direktiveproxy_passdarin gibt an, wohin die Anfrage weitergeleitet wird. -
proxy_pass und den abschließenden Schrägstrich richtig verwenden
Hier passiert der häufigste Fehler. Steht in der
proxy_pass-Adresse nach dem Servernamen ein Pfad (auch nur ein einzelnes/), ersetzt Nginx den Teil der Anfrage, der auf dielocationgepasst hat, durch diesen Pfad. Ohne Pfad wird die Adresse der Anfrage unverändert weitergegeben.location proxy_pass Eingehende Anfrage Pfad an das Backend /app/http://127.0.0.1:3000/app/login/app/login/app/http://127.0.0.1:3000//app/login/login/alt/http://127.0.0.1:3000/neu//alt/seite/neu/seite/apphttp://127.0.0.1:3000//app/login//login(falsch)Nginx# 1) KEIN Pfad in proxy_pass: Die Adresse wird unverändert weitergegeben # /app/login -> /app/login location /app/ { proxy_pass http://127.0.0.1:3000; } # 2) proxy_pass endet mit "/": Das passende Präfix wird entfernt # /api/liste -> /liste location /api/ { proxy_pass http://127.0.0.1:3001/; } # 3) proxy_pass enthält einen anderen Pfad: Das Präfix wird dadurch ersetzt # /alt/seite -> /neu/seite location /alt/ { proxy_pass http://127.0.0.1:3000/neu/; }Als Regel gilt: Lassen Sie
locationund den Pfad inproxy_passgleich enden – beide mit Schrägstrich oder gar kein Pfad inproxy_pass. Ist Ihre Anwendung für den Betrieb unter einem Unterpfad (z. B./app/) eingerichtet, behalten Sie das Präfix bei; geht sie davon aus, im Wurzelverzeichnis zu laufen, entfernen Sie es. Inlocation-Blöcken, die über einen regulären Ausdruck definiert sind, darfproxy_passkeinen Pfad enthalten; Nginx meldet beim Konfigurationstest einen Fehler.
: Vergrößern -
Die nötigen Header weiterreichen
Nginx sendet die Anfrage in eigenem Namen erneut an das Backend. Ohne zusätzliche Einstellungen sieht die Anwendung die IP-Adresse von Nginx statt der des Besuchers, und der
Host-Header enthält die Adresse ausproxy_pass. Diese vier Header übermitteln der Anwendung die fehlenden Informationen:Nginxproxy_pass http://127.0.0.1:3000; # Der Domainname, den der Besucher aufgerufen hat proxy_set_header Host $host; # IP-Adresse des Clients, der sich mit Nginx verbunden hat proxy_set_header X-Real-IP $remote_addr; # Adressen, über die die Anfrage lief (wird an die Liste angehängt) proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Vom Besucher verwendetes Schema: http oder https proxy_set_header X-Forwarded-Proto $scheme;- Host: der Domainname, den der Besucher aufgerufen hat. Die Anwendung nutzt ihn, um Links zu erzeugen und mehrere Domains zu unterscheiden.
- X-Real-IP: die IP-Adresse des Clients, der sich mit Nginx verbunden hat.
- X-Forwarded-For: die Liste der Adressen, über die die Anfrage gelaufen ist.
$proxy_add_x_forwarded_forhängt die verbindende Adresse an die vom Client gesendete Liste an. - X-Forwarded-Proto: das vom Besucher verwendete Schema (
httpoderhttps).
Achtung:
proxy_set_header-Direktiven werden von der übergeordneten Ebene nur dann geerbt, wenn auf der aktuellen Ebene überhaupt keinproxy_set_headersteht. Fügen Sie in einerlocationeinen einzelnen Header hinzu, gelten die aufserver-Ebene geschriebenen in diesem Block nicht mehr; Sie müssen alle wiederholen. -
WebSocket-Unterstützung ergänzen
Funktionen wie Live-Chat, Benachrichtigungen oder Echtzeit-Dashboards nutzen WebSocket. Ein WebSocket beginnt als gewöhnliche HTTP-Anfrage, die über den
Upgrade-Header zu einer dauerhaften Verbindung hochgestuft wird. Diese Header passieren einen Proxy nicht von selbst; sie müssen ausdrücklich weitergereicht werden, und Nginx muss mit dem Backend HTTP/1.1 sprechen.Nginx# Einmal auf http-Ebene definieren (außerhalb des server-Blocks) map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; server_name beispiel.de; location / { proxy_pass http://127.0.0.1:3000; # HTTP/1.1 und Upgrade-Header für WebSocket proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; 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; # Eine untätige WebSocket-Verbindung wird nach dieser Zeit geschlossen proxy_read_timeout 300s; } }Der
map-Block gehört auf diehttp-Ebene (außerhalb des server-Blocks): Er sorgt dafür, dassConnection: upgradegesendet wird, wenn der Client ein Upgrade verlangt hat, und andernfallsConnection: close. So funktioniert dieselbelocationfür normale Anfragen und für WebSocket.Kommen über eine WebSocket-Verbindung für die Dauer von
proxy_read_timeoutkeine Daten, schließt Nginx sie. Erhöhen Sie den Wert oder lassen Sie die Anwendung in regelmäßigen Abständen einen „Ping“ senden.
: Vergrößern -
Timeouts und Body-Größe einstellen
Direktive Was legt sie fest? Standard proxy_connect_timeoutWartezeit für den Verbindungsaufbau zum Backend 60s proxy_send_timeoutLängste Wartezeit zwischen zwei Schreibvorgängen beim Senden der Anfrage an das Backend 60s proxy_read_timeoutLängste Wartezeit zwischen zwei Lesevorgängen beim Lesen der Antwort vom Backend 60s client_max_body_sizeObergrenze für den Anfrage-Body, den ein Client senden darf (z. B. Datei-Upload) 1m Nginx# Upload-Grenze (Standard 1m); bei Überschreitung folgt 413 client_max_body_size 20m; location / { proxy_pass http://127.0.0.1:3000; proxy_connect_timeout 5s; # Verbindungsaufbau zum Backend proxy_send_timeout 60s; # Senden der Anfrage an das Backend proxy_read_timeout 60s; # Warten auf die Antwort des Backends } # Längere Wartezeit nur für die lang laufende Berichtsadresse location /berichte/ { proxy_pass http://127.0.0.1:3000; proxy_read_timeout 180s; }Die Lese- und Sende-Timeouts messen nicht die Gesamtdauer, sondern die Stille zwischen zwei Vorgängen. Sendet die Anwendung 60 Sekunden lang nichts, erhält der Besucher den Fehler 504. Wird die Upload-Grenze überschritten, antwortet Nginx mit 413; denken Sie daran, die Upload-Grenze der Anwendung selbst auf denselben Wert zu setzen. Halten Sie die Zeiten nicht länger als nötig: Eine eigene
locationfür bestimmte Adressen wie lange Berichte oder Exporte ist besser, als die Grenze für die ganze Website anzuheben. Ausführlich behandelt diese Fehler die Anleitung 502, 504 und andere Nginx-Fehler. -
Konfiguration testen und neu laden
Nginx liest seine Konfigurationsdateien nicht von selbst neu ein. Testen Sie zuerst die Syntax und laden Sie die Konfiguration neu (Reload), wenn der Test erfolgreich war. Ein Reload trennt keine offenen Verbindungen; ist die Konfiguration fehlerhaft, läuft Nginx mit den alten Einstellungen weiter.
Bash# 1) Konfiguration testen sudo nginx -t # 2) Bei erfolgreichem Test neu laden (Verbindungen bleiben bestehen) sudo systemctl reload nginx # Dasselbe auf Systemen ohne systemd: sudo nginx -s reloadnginx -tprüft nur die Syntax und den Kontext der Direktiven, nicht aber, ob das Backend erreichbar ist. Rufen Sie die Website deshalb anschließend mitcurloder im Browser auf.
: Vergrößern -
Der Anwendung beibringen, dem Proxy zu vertrauen
Auch wenn Nginx die Header sendet, verwendet die Anwendung sie nicht automatisch. Die meisten Anwendungs-Frameworks haben dafür eine Einstellung namens „Trusted Proxies“ (vertrauenswürdige Proxys): Dort tragen Sie die Adresse Ihres Reverse Proxys ein (
127.0.0.1, wenn er auf demselben Server läuft); das Framework berücksichtigt dieX-Forwarded-*-Header dann nur bei Anfragen von dieser Adresse. Name und Ort der Einstellung hängen vom verwendeten Framework ab; suchen Sie in dessen Dokumentation nach „Proxy“.Typische Symptome, wenn diese Einstellung fehlt: In den Logs erscheinen alle Besucher als
127.0.0.1, eine IP-basierte Ratenbegrenzung zählt alle als eine Person, die Anwendung hält sich fürhttpund gerät in eine endlose Weiterleitungsschleife oder erzeugt Links mithttp://.Sicherheitsregel:
X-Forwarded-*-Header kann jeder senden. Vertrauen Sie ihnen nur, wenn die Anfrage von Ihrem eigenen Reverse Proxy kommt; vermeiden Sie Einstellungen der Art „allen Adressen vertrauen“. Andernfalls kann ein Angreifer mit einem gefälschten Header IP-Beschränkungen und Ratenbegrenzungen umgehen. In einer PHP-Anwendung ohne Framework sieht dieselbe Logik so aus:PHP<?php // Nur die Adressen Ihres eigenen Reverse Proxys (127.0.0.1, wenn Nginx auf demselben Server läuft) $guvenilenProxyler = array('127.0.0.1'); $uzakAdres = $_SERVER['REMOTE_ADDR'] ?? ''; $istemciIp = $uzakAdres; $httpsMi = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'; // Die Header werden nur gelesen, wenn die Anfrage von einem vertrauenswürdigen Proxy kam if (in_array($uzakAdres, $guvenilenProxyler, true)) { $gercekIp = $_SERVER['HTTP_X_REAL_IP'] ?? ''; if (filter_var($gercekIp, FILTER_VALIDATE_IP) !== false) { $istemciIp = $gercekIp; } $httpsMi = ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https'; }Das Beispiel liest den Header
X-Real-IP, weil Nginx ihn bei jeder Anfrage mit der tatsächlich gesehenen Adresse überschreibt.X-Forwarded-Fordagegen hängt an den vom Client gesendeten Wert an; die erste Adresse der Liste kann gefälscht sein, verlässlich ist die letzte, von Ihrem Proxy hinzugefügte Adresse.
: Vergrößern
Vollständige Beispielkonfiguration
Die folgende Datei fasst alle bisherigen Schritte zusammen. Ersetzen Sie die Domain und die Adresse der Anwendung durch Ihre eigenen.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name beispiel.de www.beispiel.de;
# Obergrenze für den Anfrage-Body (Datei-Uploads)
client_max_body_size 20m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# Damit die Anwendung die echte Domain, die IP und das Schema sieht
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;
# WebSocket
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Timeouts
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}Um HTTPS zu ergänzen, fahren Sie mit der Anleitung HTTPS in Nginx fort. Sobald HTTPS aktiv ist, wird die Variable $scheme von selbst zu https; die Header-Zeilen müssen Sie nicht ändern. Für die Verteilung auf mehrere Anwendungsserver siehe die Anleitung zur Lastverteilung.
Häufige Fehler
- Unpassende Schrägstriche:
location /apiwird mitproxy_pass …/kombiniert; beim Backend kommt//pfadan oder die Anwendung antwortet mit 404. - Host-Header vergessen: Die Anwendung erzeugt Links mit
127.0.0.1:3000oder zeigt die falsche Website. - Einen einzelnen Header in einer location schreiben: Die übrigen
proxy_set_header-Zeilen der übergeordneten Ebene werden in diesem Block nicht geerbt. - WebSocket vergessen: Die Seite lädt, aber Live-Funktionen arbeiten nicht; in der Browserkonsole steht ein Verbindungsfehler.
- Das Backend zum Internet offen lassen: Lauscht die Anwendung auf
0.0.0.0, lassen sich alle Grenzen und Zugriffsregeln in Nginx umgehen. - Neustart ohne Test: Ein Neustart (Restart) mit fehlerhafter Konfiguration kann dazu führen, dass Nginx gar nicht mehr startet. Erst
nginx -t, dann neu laden. - In der Anwendung allen vertrauen: Wer die Liste der vertrauenswürdigen Proxys auf „alle Adressen“ setzt, akzeptiert auch gefälschte Header.
Die Einrichtung überprüfen
- Rufen Sie die Anwendung direkt vom Server aus auf: Kommt eine Antwort, läuft das Backend.
- Stellen Sie dieselbe Anfrage mit dem Domainnamen über Nginx: Ist die Antwort gleich, funktioniert der Proxy.
- Prüfen Sie von außerhalb des Servers, dass
http://server-ip:3000nicht erreichbar ist. - Kontrollieren Sie im Log der Anwendung, dass als Besucher-IP die echte Adresse und nicht
127.0.0.1erscheint. - Bei Problemen sehen Sie in das Nginx-Fehlerlog; in den meisten Installationen ist das
/var/log/nginx/error.log.
# Vom Server aus: Antwortet die Anwendung direkt?
curl -I http://127.0.0.1:3000/
# Über Nginx: Kommt mit dem Domainnamen dieselbe Antwort?
curl -I http://beispiel.de/
# Bei Fehlern die letzten Logzeilen (Pfad in den meisten Installationen)
sudo tail -n 50 /var/log/nginx/error.logHäufige Fragen
Soll am Ende von proxy_pass ein Schrägstrich stehen?
Das hängt davon ab, unter welchem Pfad Ihre Anwendung die Anfrage erwartet. Mit Schrägstrich (oder einem anderen Pfad) ersetzt Nginx das von der location erfasste Präfix durch diesen Pfad; ohne gibt es die Adresse unverändert weiter. Im einfachen Fall, in dem Sie die ganze Website mit „location /“ weiterleiten, liefern beide dasselbe Ergebnis.
Warum sieht meine Anwendung alle Besucher als 127.0.0.1?
Weil nicht der Besucher, sondern Nginx die Verbindung aufbaut. Reichen Sie in Nginx die Header X-Real-IP und X-Forwarded-For weiter und tragen Sie in der Anwendung die Adresse Ihres Reverse Proxys als vertrauenswürdigen Proxy ein.
Was ist der Unterschied zwischen Reload und Restart?
Ein Reload übernimmt die Konfiguration, ohne offene Verbindungen zu trennen; ist die Konfiguration fehlerhaft, läuft Nginx mit den alten Einstellungen weiter. Ein Restart stoppt und startet Nginx; mit fehlerhafter Konfiguration startet es möglicherweise gar nicht. Für alltägliche Änderungen genügt ein Reload.
Was ändert sich, wenn die Anwendung auf einem anderen Server läuft?
In proxy_pass tragen Sie die interne Netzwerkadresse dieses Servers ein (z. B. http://10.0.0.5:3000). Binden Sie die Anwendung an die interne Adresse, öffnen Sie den Port in der Firewall nur für den Nginx-Server und tragen Sie dessen interne Adresse in die Liste der vertrauenswürdigen Proxys der Anwendung ein.
Muss auch der Verkehr zwischen Nginx und der Anwendung verschlüsselt sein?
Laufen beide auf demselben Server, verlässt der Verkehr den Server nicht; HTTPS in Nginx zu beenden (SSL-/TLS-Terminierung) ist eine verbreitete und ausreichende Lösung. Führt der Weg über ein Netz, dem Sie nicht vertrauen, sollten Sie auch die Verbindung zum Backend verschlüsseln.
BYK Yazılım Support-Team
Diese Anleitung wird vom Support-Team von BYK Yazılım erstellt und regelmäßig überprüft. Letzte Aktualisierung: 04.10.2026.
Verwandte Anleitungen
- Was ist ein Reverse Proxy?Aufgaben eines Reverse Proxys, typische Architekturen, echte Besucher-IP und Header, Verhältnis zum CDN und ein kurzes Nginx-Beispiel.
- HTTPS in Nginx: SSL-Zertifikat einrichtenZertifikat beziehen, auf HTTPS weiterleiten, HSTS, SSL-Terminierung und automatische Erneuerung in Nginx.
- 502, 504 und andere Nginx-Fehler: Ursachen und LösungenBedeutung, mögliche Ursachen, Diagnose über die Logs und Lösung für 502, 504, 413, 499, 403 und 404.
- Was ist Lastverteilung (Load Balancing)?Wie Anfragen auf mehrere Server verteilt werden, die upstream-Einstellungen in Nginx, Zustandsprüfung und das Sitzungsproblem.
Sprechen wir über die Infrastruktur Ihrer Website
BYK Yazılım entwickelt Unternehmenswebsites. Schreiben Sie uns bei Fragen zu Ihrer Website.
Kontakt aufnehmen Unternehmenswebsite