Nginx: Webserver und Reverse-Proxy für moderne Web-Infrastruktur einrichten

Hinter den meisten modernen Webseiten und APIs steht ein Stück Software, das kaum jemand direkt sieht, aber alles zusammenhält: der Webserver. Nginx (ausgesprochen „Engine X") hat sich seit seiner Veröffentlichung 2004 zur dominanten Kraft entwickelt – es bedient laut Netcraft über 30 Prozent aller aktiven Webseiten weltweit. Der Grund liegt in seiner Event-getriebenen Architektur: Nginx kann Zehntausende gleichzeitige Verbindungen mit minimalem Speicherverbrauch verwalten, weil es Anfragen nicht wie Apache in separaten Threads, sondern asynchron in einem einzigen Prozess abarbeitet.

Was Nginx kann – und was es ist

Nginx übernimmt in modernen Infrastrukturen mehrere Rollen gleichzeitig: Als Webserver liefert es statische Dateien (HTML, CSS, Bilder) extrem schnell aus. Als Reverse-Proxy leitet es Anfragen an Anwendungsserver wie Node.js, Python oder PHP-FPM weiter und schirmt diese vom direkten Internet ab. Als Load Balancer verteilt es Last auf mehrere Backend-Instanzen. Als TLS-Terminator handhabt es HTTPS, damit Backends sich nicht um SSL kümmern müssen.

Statische Dateien ausliefern

Die grundlegendste Konfiguration serviert statische Dateien aus einem Verzeichnis. Konfigurationsdateien für Webseiten liegen unter /etc/nginx/sites-available/ und werden per Symlink nach /etc/nginx/sites-enabled/ aktiviert:

server {
    listen 80;
    server_name beispiel.de www.beispiel.de;

    root /var/www/beispiel.de/public;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    # Caching-Header für statische Assets
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Der server_name-Block definiert, für welche Domains diese Konfiguration gilt. location-Blöcke erlauben es, unterschiedliche Verarbeitungsregeln für verschiedene URL-Pfade festzulegen – eine der mächtigsten Funktionen in Nginx.

Reverse-Proxy für Node.js und PHP

Das häufigste Einsatzszenario: Nginx nimmt externe Anfragen entgegen und leitet sie an eine lokal laufende Anwendung weiter:

# Reverse Proxy für Node.js (läuft auf Port 3000)
server {
    listen 80;
    server_name api.beispiel.de;

    location / {
        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_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

# PHP-FPM für WordPress/Laravel
location ~ \.php$ {
    fastcgi_pass    unix:/run/php/php8.3-fpm.sock;
    fastcgi_index   index.php;
    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include         fastcgi_params;
}

Die Header X-Real-IP und X-Forwarded-For sind wichtig, damit die Anwendung die echte Client-IP-Adresse sieht – nicht die Loopback-Adresse des Proxys.

Tipp: Nach jeder Konfigurationsänderung die Syntax prüfen und sanft neu laden: nginx -t && systemctl reload nginx. Der Reload-Befehl startet Nginx nicht neu – bestehende Verbindungen bleiben aktiv, nur neue Anfragen nutzen die aktualisierte Konfiguration.

SSL mit Let's Encrypt und Certbot

HTTPS ist heute Pflicht. Let's Encrypt bietet kostenlose, automatisch verlängerbare TLS-Zertifikate. Mit Certbot ist die Einrichtung auf Ubuntu/Debian ein Zweizeiler:

apt install certbot python3-certbot-nginx
certbot --nginx -d beispiel.de -d www.beispiel.de

Certbot erkennt die Nginx-Konfiguration automatisch, beantragt das Zertifikat und ergänzt die HTTPS-Server-Blöcke. Die automatische Verlängerung übernimmt ein Systemd-Timer. Das Ergebnis sieht dann ungefähr so aus:

server {
    listen 443 ssl;
    server_name beispiel.de;

    ssl_certificate     /etc/letsencrypt/live/beispiel.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/beispiel.de/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    # ... rest der Konfiguration
}

Gzip-Komprimierung und Rate Limiting

Zwei Optimierungen, die mit wenigen Zeilen großen Effekt haben:

# Gzip in nginx.conf (http-Block)
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript
           text/xml application/xml image/svg+xml;

# Rate Limiting (server- oder location-Block)
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

location /api/ {
    limit_req zone=api burst=20 nodelay;
    proxy_pass http://127.0.0.1:3000;
}

Gzip reduziert die Übertragungsgröße typischer HTML/JSON-Antworten um 60–80 Prozent. Das Rate Limiting erlaubt 10 Anfragen pro Sekunde pro IP, mit einem Burst von 20 Anfragen – danach antwortet Nginx mit HTTP 429, bevor der Backend-Server überhaupt belastet wird.

Achtung: Gzip sollte für bereits komprimierte Formate wie JPEG, PNG, ZIP oder WOFF2 deaktiviert bleiben – nochmaliges Komprimieren vergrößert diese Dateien und belastet die CPU ohne Nutzen. Die obige gzip_types-Liste enthält bewusst keine Binärformate.

Nginx vs. Apache vs. Caddy vs. Traefik

Merkmal Nginx Apache Caddy Traefik
Architektur Event-driven, async Threaded / Event MPM Event-driven, async Event-driven, async
Konfigurationsstil Eigene Syntax (Blöcke) .htaccess / Apache-Syntax Caddyfile (minimalistisch) YAML / Docker Labels
Automatisches SSL Nein (Certbot nötig) Nein (Certbot nötig) Ja (eingebaut) Ja (eingebaut)
Performance (statisch) Sehr hoch Mittel Hoch Hoch
Typischer Einsatz Web, API, LB PHP, .htaccess-Applikationen Einfacher HTTPS-Server Container-Umgebungen
Lernkurve Mittel Mittel Gering Mittel (mit Docker vertraut sein)

Weiterführende Ressourcen

Die offizielle Nginx-Dokumentation ist umfassend und enthält vollständige Referenzen aller Direktiven. Für optimale Sicherheitseinstellungen empfiehlt sich der Mozilla SSL Configuration Generator, der aktuelle, gehärtete SSL-Konfigurationen für Nginx und andere Server generiert. Wer Nginx in Container-Umgebungen einsetzen möchte, findet mit Traefik eine ausgezeichnete Alternative mit automatischer Service Discovery.

Häufige Fragen zu Nginx

Was ist der Unterschied zwischen location = /pfad, location /pfad und location ~ /regex?
Nginx wertet Location-Blöcke in einer definierten Reihenfolge aus. location = /pfad ist eine exakte Übereinstimmung mit höchster Priorität. location /pfad ist eine Präfix-Übereinstimmung. location ~ ist ein regulärer Ausdruck (case-sensitive), location ~* case-insensitiv. Der genaueste Match gewinnt, wobei exakte Übereinstimmungen immer Vorrang haben.
Wie konfiguriere ich Nginx als Load Balancer für mehrere Backend-Server?
Mit dem upstream-Block: upstream backend { server 10.0.0.1:3000; server 10.0.0.2:3000; }. Dann in der Location: proxy_pass http://backend;. Standard ist Round-Robin. Alternativ sind least_conn (wenigste aktive Verbindungen) oder ip_hash (Sticky Sessions) konfigurierbar.
Nginx startet nicht – wie debugge ich Konfigurationsfehler?
nginx -t prüft die Konfiguration und gibt die genaue Fehlerstelle aus. Detailliertere Logs finden sich in /var/log/nginx/error.log. Häufige Fehler sind fehlende Semikolons, nicht übereinstimmende geschweifte Klammern oder Pfade zu nicht existierenden Zertifikatsdateien.
Kann Nginx HTTP/3 und QUIC unterstützen?
Ja, ab Nginx 1.25 ist experimentelle HTTP/3-Unterstützung (QUIC) eingebaut. Sie muss beim Kompilieren aktiviert oder über offizielle Pakete von nginx.org bezogen werden. Die Konfiguration erfordert listen 443 quic reuseport; neben dem normalen HTTPS-Listener und einen entsprechenden add_header Alt-Svc-Header.