TL;DR — Kurzzusammenfassung
Nginx als Reverse Proxy und Load Balancer mit SSL einrichten. Behandelt proxy_pass, Let's Encrypt, Balancing-Algorithmen, WebSocket, Caching und Rate-Limiting.
Nginx betreibt über 34 % der meistbesuchten Websites der Welt — und ein großer Teil dieses Datenverkehrs fließt durch ihn nicht als Webserver, sondern als Reverse Proxy und Load Balancer. Nginx als Reverse Proxy mit SSL-Termination zu konfigurieren, bietet einen einzigen gehärteten Einstiegspunkt, der die Last auf Backend-Server verteilt, TLS von Ihrer Anwendung abnimmt und Caching, Rate Limiting und Sicherheits-Header an einem Ort hinzufügt. Diese Anleitung deckt jede Schicht dieses Stacks ab: Grundlagen des Reverse Proxy, SSL-Termination mit Let’s Encrypt, alle vier Load-Balancing-Algorithmen, WebSocket-Proxying, Response-Caching, Rate Limiting, Sicherheits-Header, HTTP/2 und HTTP/3, Monitoring und ein praxisnahes Node.js-Cluster-Szenario.
Voraussetzungen
Stellen Sie sicher, dass Sie folgendes haben:
- Ubuntu 22.04 oder 24.04 (Befehle gelten für jede Debian-basierte Distribution)
- Nginx 1.18 oder höher (
sudo apt install nginx) - Eine registrierte Domain, die auf die öffentliche IP Ihres Servers zeigt
- Terminalzugriff mit sudo-Rechten
- Mindestens zwei Backend-Anwendungsserver oder -Prozesse (für Load Balancing)
Grundlagen des Reverse Proxy
Ein Reverse Proxy befindet sich zwischen dem Internet und einem oder mehreren Backend-Servern. Clients verbinden sich mit Nginx; Nginx leitet die Anfrage an das entsprechende Backend weiter und gibt die Antwort zurück. Der Backend-Server benötigt niemals eine öffentliche IP-Adresse.
Die zentrale Direktive ist proxy_pass:
server {
listen 80;
server_name app.beispiel.de;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}
Die vier proxy_set_header-Direktiven sind in jeder Produktionskonfiguration unerlässlich. Ohne X-Forwarded-For zeigen Ihre Anwendungslogs nur die IP des Nginx-Servers. Ohne X-Forwarded-Proto kann Ihre App HTTP von HTTPS nicht unterscheiden und kann fehlerhafte Redirect-Schleifen erzeugen.
Legen Sie sinnvolle Timeouts fest, damit langsame Backends keine Nginx-Worker blockieren:
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 16k;
SSL-Termination mit Let’s Encrypt
SSL-Termination bedeutet, dass Nginx den TLS-Handshake verwaltet und einfaches HTTP an Backends im internen Netzwerk weiterleitet — ohne TLS-Overhead auf den einzelnen Anwendungsservern.
Installieren Sie Certbot mit dem Nginx-Plugin:
sudo apt install certbot python3-certbot-nginx -y
Erhalten und installieren Sie ein Zertifikat (Certbot ändert Ihren server-Block automatisch):
sudo certbot --nginx -d app.beispiel.de -d www.app.beispiel.de
Certbot erstellt einen systemd-Timer, der Zertifikate automatisch vor dem Ablauf erneuert:
sudo systemctl status certbot.timer
sudo certbot renew --dry-run
Load-Balancing-Algorithmen
Um die Last auf mehrere Backends zu verteilen, ersetzen Sie das einzelne proxy_pass-Ziel durch einen upstream-Block:
upstream app_cluster {
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
Round-Robin (Standard)
Keine Direktive erforderlich. Nginx verteilt Anfragen sequenziell auf alle Upstream-Server. Fügen Sie Gewichte hinzu, um mehr Datenverkehr zu leistungsfähigeren Knoten zu leiten:
upstream app_cluster {
server 10.0.0.10:3000 weight=3;
server 10.0.0.11:3000 weight=1;
server 10.0.0.12:3000 weight=1;
}
Wenigste Verbindungen (least_conn)
Nginx leitet jede neue Anfrage an den Upstream-Server mit den wenigsten aktiven Verbindungen weiter. Ideal für Workloads mit variablen Antwortzeiten:
upstream app_cluster {
least_conn;
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
IP-Hash (ip_hash)
Die Client-IP bestimmt, welches Backend alle Anfragen von diesem Client bedient. Nützlich für Session-Persistenz ohne gemeinsamen Session-Speicher:
upstream app_cluster {
ip_hash;
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
Zufällig (random)
Nginx wählt ein Backend zufällig aus. Mit dem Parameter two wählt es zwei Server zufällig und leitet an den mit weniger Verbindungen weiter:
upstream app_cluster {
random two least_conn;
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
Upstream-Gesundheitsprüfungen
Markieren Sie Server als Backup oder setzen Sie Fehlerschwellenwerte, damit Nginx aufhört, Datenverkehr an nicht verfügbare Backends zu senden:
upstream app_cluster {
least_conn;
server 10.0.0.10:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.11:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.12:3000 backup;
}
WebSocket-Proxying
WebSocket-Verbindungen erfordern einen HTTP/1.1-Upgrade-Handshake. Fügen Sie drei Direktiven zu jedem location-Block hinzu, der WebSocket-Datenverkehr weiterleitet:
location /ws/ {
proxy_pass http://app_cluster;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Caching mit proxy_cache
Nginx kann Upstream-Antworten im Arbeitsspeicher oder auf der Festplatte zwischenspeichern, was die Backend-Last bei cachebaren Endpunkten erheblich reduziert.
Definieren Sie eine Cache-Zone im http-Kontext:
http {
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=app_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
}
Aktivieren Sie Caching im location-Block:
location /api/public/ {
proxy_pass http://app_cluster;
proxy_cache app_cache;
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;
}
Rate Limiting
Rate Limiting schützt Backends vor Traffic-Spitzen und Brute-Force-Angriffen. Definieren Sie eine gemeinsame Speicherzone im http-Kontext:
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/m;
}
Wenden Sie die Zone auf einen location an:
location /api/ {
limit_req zone=api_limit burst=10 nodelay;
limit_req_status 429;
proxy_pass http://app_cluster;
}
Sicherheits-Header
Fügen Sie Sicherheits-Header im server-Block hinzu:
server {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" always;
server_tokens off;
}
HTTP/2 und HTTP/3
Aktivieren Sie HTTP/2 in der listen-Direktive:
listen 443 ssl http2;
Für HTTP/3 (Nginx 1.25+):
listen 443 ssl http2;
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400' always;
Monitoring mit stub_status
Aktivieren Sie das stub_status-Modul, um Echtzeit-Verbindungsmetriken bereitzustellen:
server {
listen 127.0.0.1:8080;
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
}
curl http://127.0.0.1:8080/nginx_status
Vergleich: Nginx vs. Alternativen
| Funktion | Nginx | HAProxy | Traefik | Caddy |
|---|---|---|---|---|
| Protokollunterstützung | HTTP, HTTPS, TCP, UDP | HTTP, HTTPS, TCP | HTTP, HTTPS, TCP, gRPC | HTTP, HTTPS |
| Balancing-Algorithmen | RR, LC, IP-Hash, random | RR, LC, source, URI | RR, WRR | RR, LC |
| Aktive Health-Checks | Nur Nginx Plus | Ja (eingebaut) | Ja (eingebaut) | Ja (eingebaut) |
| Auto-SSL (ACME) | Via Certbot | Via Certbot | Eingebaut | Eingebaut |
| Eingebautes Caching | Ja | Nein | Nein | Nein |
| HTTP/3 | 1.25+ (experimentell) | Nein | Nein | Ja |
| Am besten für | Web + Proxy + Cache | Reines TCP/HTTP-LB | Kubernetes-Ingress | Einfaches Auto-SSL |
Praxisszenario: Load Balancing eines Node.js-Clusters mit SSL
Sie haben eine produktive Node.js-API, die drei PM2-Prozesse auf demselben Host ausführt (Ports 3001, 3002, 3003). Sie möchten sie als api.beispiel.de über HTTPS mit Session-Affinität, Rate Limiting am Authentifizierungsendpunkt und WebSocket-Unterstützung bereitstellen.
upstream node_api {
ip_hash;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
limit_req_zone $binary_remote_addr zone=auth_limit:5m rate=5r/m;
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=60r/m;
server {
listen 443 ssl http2;
server_name api.beispiel.de;
ssl_certificate /etc/letsencrypt/live/api.beispiel.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.beispiel.de/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
server_tokens off;
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://node_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/auth/ {
limit_req zone=auth_limit burst=3 nodelay;
limit_req_status 429;
proxy_pass http://node_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /ws/ {
proxy_pass http://node_api;
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-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 3600s;
}
}
server {
listen 80;
server_name api.beispiel.de;
return 301 https://$host$request_uri;
}
Häufige Fehler und Sonderfälle
Der abschließende Schrägstrich in proxy_pass ist wichtig. proxy_pass http://backend; behält den vollständigen URI einschließlich des /api/-Präfixes. proxy_pass http://backend/; entfernt das location-Präfix und kann schwer zu diagnostizierende 404-Fehler verursachen.
Verwenden Sie ip_hash nicht, wenn ein CDN vor Nginx liegt. Aller CDN-Traffic scheint von einer kleinen Menge von CDN-IP-Adressen zu kommen, sodass ip_hash den gesamten CDN-Traffic an ein einzelnes Backend sendet.
Lange Verbindungen und SSE erfordern größere Timeouts. Server-Sent Events (SSE) und Long-Polling-Verbindungen bleiben auf unbestimmte Zeit offen. Passen Sie proxy_read_timeout an das Heartbeat-Intervall Ihrer Anwendung plus einen Puffer an.
proxy_buffering und Streaming. Wenn Ihr Backend eine Antwort streamt (SSE, Chunked Transfer), setzen Sie proxy_buffering off für diesen location. Andernfalls puffert Nginx die vollständige Antwort, bevor er sie sendet, was den Zweck des Streamings zunichte macht.
Fehlerbehebung
502 Bad Gateway. Das Backend läuft nicht oder hört nicht auf dem konfigurierten Port. Prüfen Sie: sudo systemctl status ihre-app, ss -tlnp | grep 3000.
504 Gateway Timeout. Das Backend antwortet zu langsam. Erhöhen Sie proxy_read_timeout oder untersuchen Sie die Backend-Performance.
WebSocket-Verbindungen brechen nach 60 Sekunden ab. Nginx’s Standard-proxy_read_timeout beträgt 60 Sekunden. Erhöhen Sie ihn für WebSocket-locations.
Cache funktioniert nicht. Stellen Sie sicher, dass proxy_cache_path im http-Kontext definiert ist, das Verzeichnis existiert und vom nginx-Benutzer beschreibbar ist, und dass proxy_cache im richtigen location-Block konfiguriert ist.
Zusammenfassung
Nginx als Reverse Proxy und Load Balancer bietet eine produktionsreife Traffic-Schicht ohne zusätzliche Infrastruktur. Wichtigste Erkenntnisse:
- Setzen Sie immer
X-Forwarded-For,X-Forwarded-ProtoundHostin jedem Proxy-location - Verwenden Sie
certbot --nginxfür unterbrechungsfreie SSL-Zertifikatsbereitstellung mit automatischer Erneuerung - Wählen Sie
least_connfür APIs,ip_hashfür Session-Persistenz undrandom two least_connfür große Backend-Pools - Markieren Sie Backends mit
max_failsundfail_timeout, damit Nginx nicht verfügbare Server automatisch entfernt - Verwenden Sie
proxy_http_version 1.1mit Upgrade/Connection-Headern für WebSocket-Proxying - Aktivieren Sie
proxy_cachefür öffentliche Endpunkte undlimit_req_zonezum Schutz von Authentifizierungsrouten - Aktivieren Sie
http2in der listen-Direktive für Multiplexing; evaluieren Siequicbei Nginx 1.25+
Verwandte Artikel
- Anleitung: Eigene Version von NginX kompilieren
- Fail2Ban: Linux-Server vor Brute-Force-Angriffen schützen
- UFW-Firewall auf Ubuntu Server konfigurieren: Vollständige Anleitung
- Nginx die korrekte Client-IP-Adresse über einen Varnish-Reverse-Proxy übergeben
- Linux-Server-Sicherheitscheckliste: 20 wesentliche Schritte