Nginx Performance-Tuning auf einem VPS

12 Min. Lesezeit·Matthieu·vpslinuxperformancenginx|

Nginx für Produktions-Traffic auf einem Linux-VPS optimieren. Worker-Prozesse, Kompression, Caching, HTTP/2, TLS-Optimierung, Kernel-Sysctl und Benchmarks mit wrk.

Eine Standard-Nginx-Installation bewältigt moderaten Traffic problemlos. Aber die Standardwerte sind konservativ. Auf einem VPS mit 4 vCPUs und 8 GB RAM können Sie deutlich mehr Requests pro Sekunde ausliefern, wenn Sie Worker-Prozesse, Kompression, Caching und Kernel-Parameter anpassen. Diese Anleitung geht Schicht für Schicht durch, mit Benchmarks als Nachweis für jede Änderung.

Wir setzen voraus, dass Nginx bereits installiert ist und Traffic ausliefert. Falls nicht, beginnen Sie mit der Anleitung zur Nginx-Administration auf einem VPS.

Alle Beispiele beziehen sich auf Nginx Mainline unter Debian 12 oder Ubuntu 24.04. Die Konfigurationsdateistruktur wird in der Anleitung zur Nginx-Konfigurationsdateistruktur behandelt.

Wie erstellen Sie eine Performance-Baseline für Nginx?

Bevor Sie etwas ändern, messen Sie die aktuelle Leistung mit wrk. Das gibt Ihnen eine Baseline zum Vergleich nach dem Tuning. Ohne Zahlen raten Sie nur.

Installieren Sie wrk auf einer separaten Maschine (Ihrer lokalen Workstation oder einem anderen VPS). Benchmarken Sie niemals vom selben Server, den Sie testen. Das Benchmark-Tool und der Webserver konkurrieren um CPU, und die Ergebnisse werden wertlos.

apt install wrk

Führen Sie einen 30-Sekunden-Test mit 4 Threads und 200 Verbindungen gegen eine statische Seite durch:

wrk -t4 -c200 -d30s https://your-server.example.com/
Running 30s test @ https://your-server.example.com/
  4 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    12.34ms    5.67ms  89.12ms   78.45%
    Req/Sec     4.12k   312.45     5.23k    72.50%
  493440 requests in 30.01s, 1.92GB read
Requests/sec:  16442.18
Transfer/sec:     65.52MB

Notieren Sie vier Werte: Requests/sec, durchschnittliche Latenz, maximale Latenz und Transfer/sec. Das ist Ihre Baseline.

Wie viele Worker-Prozesse und Verbindungen sollte Nginx verwenden?

Setzen Sie worker_processes auto, um einen Worker pro CPU-Kern zu starten. Auf einem VPS mit 4 vCPUs bedeutet das 4 Workers. Jeder Worker ist single-threaded und verarbeitet Verbindungen unabhängig über epoll. Ein Worker pro Kern vermeidet den Overhead durch Context Switching.

Die Formel für maximale gleichzeitige Verbindungen:

max Verbindungen = worker_processes x worker_connections

vCPUs worker_processes worker_connections Max Verbindungen
1 1 2048 2.048
2 2 2048 4.096
4 4 2048 8.192
8 8 2048 16.384

Jede Verbindung verbraucht einen Dateideskriptor. Setzen Sie worker_rlimit_nofile höher als worker_connections, um das OS-Limit nicht zu erreichen. Ein sicherer Wert ist worker_connections * 2, was Upstream-Verbindungen beim Proxying berücksichtigt.

Bearbeiten Sie /etc/nginx/nginx.conf:

worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 8192;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

worker_cpu_affinity auto bindet jeden Worker an einen CPU-Kern und reduziert Cache-Misses durch Prozessmigration. multi_accept on lässt einen Worker alle wartenden Verbindungen auf einmal annehmen statt einzeln. use epoll ist der Standard unter Linux, aber es lohnt sich, explizit zu sein.

Die accept_mutex-Direktive steht seit Nginx 1.11.3 standardmäßig auf off, weil Linux-Kernel ab 4.5 EPOLLEXCLUSIVE unterstützen, das Verbindungen ohne Mutex auf die Worker verteilt. Lassen Sie sie deaktiviert.

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
systemctl reload nginx

Welche TCP-Direktiven verbessern den Nginx-Durchsatz?

Drei Direktiven arbeiten zusammen, um den Datenversand von Nginx über TCP zu optimieren. sendfile umgeht den Userspace-Buffer, indem Daten direkt zwischen Dateideskriptoren im Kernel kopiert werden. tcp_nopush fasst Response-Header und den Anfang einer Datei in ein einzelnes TCP-Paket zusammen. tcp_nodelay deaktiviert Nagles Algorithmus, damit kleine Pakete (wie das Ende einer Antwort) sofort gesendet werden.

Fügen Sie diese zum http-Block in /etc/nginx/nginx.conf hinzu:

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    #...bestehende Direktiven...
}

sendfile macht den größten Unterschied beim Ausliefern statischer Dateien. Ohne diese Direktive liest Nginx die Datei in einen Buffer, dann schreibt es den Buffer zum Socket. Zwei Kopien. Mit sendfile führt der Kernel einen Zero-Copy-Transfer durch. Auf einem ausgelasteten Dateiserver reduziert das allein die CPU-Nutzung spürbar.

tcp_nopush und tcp_nodelay widersprechen sich nicht. Nginx wendet tcp_nopush beim Aufbau der Antwort an und wechselt dann für das letzte Paket zu tcp_nodelay. Das Ergebnis: weniger Pakete insgesamt, ohne Verzögerung beim letzten.

Wie konfigurieren Sie Keepalive-Verbindungen für Nginx?

Keepalive-Verbindungen ermöglichen einem Client, eine TCP-Verbindung für mehrere HTTP-Requests wiederzuverwenden. Das vermeidet den Overhead von TCP-Handshakes und TLS-Aushandlung bei jedem Request. Ein einzelner Seitenaufruf kann 20-50 Unteranfragen für CSS, JS, Bilder und Schriftarten auslösen.

http {
    keepalive_timeout 65;
    keepalive_requests 1000;

    #...bestehende Direktiven...
}

keepalive_timeout 65 schließt inaktive Verbindungen nach 65 Sekunden. Zu hoch verschwendet Dateideskriptoren für inaktive Clients. Zu niedrig erzwingt Neuverbindungen. 65 Sekunden ist ein vernünftiger Standard für die meisten Workloads.

keepalive_requests 1000 erlaubt bis zu 1.000 Requests pro Verbindung, bevor Nginx sie schließt. Der Standardwert ist 1000 seit Nginx 1.19.10. Wenn Sie hinter einem Load Balancer sitzen, der viele Requests pro Verbindung sendet, erhöhen Sie auf 10000.

Upstream-Keepalive

Wenn Nginx als Proxy zu einem Backend (Node.js, Python, Go) dient, verhindern Upstream-Keepalive-Verbindungen, dass Nginx bei jedem Request eine neue TCP-Verbindung zum Backend öffnet. Hier verschwenden die meisten Proxy-Setups Zeit.

upstream backend {
    server 127.0.0.1:3000;
    keepalive 64;
}

server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

keepalive 64 hält 64 inaktive Verbindungen zum Backend pro Worker offen. proxy_http_version 1.1 ist erforderlich, da Keepalive ein HTTP/1.1-Feature ist. Der leere Connection-Header löscht den Connection: close-Header des Clients, damit Nginx ihn nicht ans Backend weiterleitet.

Mehr zur Proxy-Konfiguration finden Sie in der Anleitung zum Nginx Reverse Proxy.

Wie dimensionieren Sie die Proxy-Buffer von Nginx?

Wenn Nginx einen Request weiterleitet, puffert es die Antwort des Backends. Ist der Buffer zu klein, schreibt Nginx die Antwort in eine temporäre Datei auf der Festplatte. Festplatten-I/O ist um Größenordnungen langsamer als RAM.

http {
    proxy_buffer_size 16k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;

    client_body_buffer_size 16k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    #...bestehende Direktiven...
}

proxy_buffer_size 16k verarbeitet die Response-Header vom Backend. Die meisten Header passen in 4k-8k, aber Anwendungen mit vielen Cookies oder benutzerdefinierten Headern brauchen mehr. 16k ist sicher, ohne verschwenderisch zu sein.

proxy_buffers 4 32k weist 4 Buffer mit je 32k zu (insgesamt 128k pro Verbindung) für den Response-Body. Dimensionieren Sie diese nach Ihrer typischen Antwortgröße. API-Antworten unter 100k passen bequem. Wenn Sie große Payloads ausliefern, erhöhen Sie die Anzahl der Buffer statt deren Größe.

proxy_busy_buffers_size 64k steuert, wie viele gepufferte Daten Nginx an den Client senden kann, während es noch vom Backend liest. Der Wert sollte die Summe von proxy_buffers nicht überschreiten.

Achten Sie auf diese Meldung im Error-Log:

an upstream response is buffered to a temporary file

Wenn Sie sie häufig sehen, erhöhen Sie proxy_buffers. Prüfen Sie das Log:

journalctl -u nginx --no-pager | grep "temporary file"

Wie konfigurieren Sie Caching statischer Dateien in Nginx?

Caching statischer Dateien weist Browser an, Assets lokal zu speichern. Das eliminiert wiederholte Requests vollständig. Für Assets mit gehashten Dateinamen (wie app.a1b2c3.js) setzen Sie aggressives Ablaufdatum. Für HTML halten Sie es kurz.

server {
    location ~* \.(css|js|woff2|woff|ttf|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~* \.(jpg|jpeg|png|gif|ico|webp|avif)$ {
        expires 30d;
        add_header Cache-Control "public";
        access_log off;
    }

    location ~* \.html$ {
        expires 1h;
        add_header Cache-Control "public, no-cache";
    }
}

immutable teilt dem Browser mit, das Asset überhaupt nicht zu revalidieren. Verwenden Sie das nur für Dateien mit Fingerprint-Namen. access_log off bei statischen Assets reduziert Festplatten-I/O durch Logging.

Zu Cache-Headern und deren Zusammenspiel mit Sicherheits-Headern siehe.

open_file_cache

Nginx kann Dateideskriptoren, Änderungszeiten und Existenzprüfungen für häufig aufgerufene Dateien cachen. Das vermeidet wiederholte stat()- und open()-Systemaufrufe.

http {
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
}

max=10000 hält bis zu 10.000 Einträge. Dimensionieren Sie dies nach der Anzahl statischer Dateien, die Sie ausliefern. Bei 500 Dateien reicht max=1000. Bei 50.000 Assets von einem CDN-Origin erhöhen Sie entsprechend.

inactive=30s entfernt Einträge, die 30 Sekunden nicht abgerufen wurden. open_file_cache_min_uses 2 cached nur Dateien, die im inactive-Zeitfenster mindestens zweimal aufgerufen wurden. Das verhindert, dass einmalige Requests den Cache verunreinigen.

open_file_cache_errors on cached auch 404-Lookups. Wenn ein Client wiederholt eine nicht existierende Datei anfragt, antwortet Nginx aus dem Cache, statt jedes Mal das Dateisystem zu bemühen.

Wie aktivieren Sie gzip- und Brotli-Kompression in Nginx?

Gzip auf Stufe 4-6 bietet den besten Kompromiss zwischen CPU-Kosten und Kompressionsrate. Über Stufe 6 gewinnt man weniger als 2 % Kompression bei doppelter CPU-Zeit. Brotli auf Stufe 4 erreicht typischerweise bessere Kompression als gzip auf Stufe 9, bei ähnlichen CPU-Kosten.

Gzip

http {
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_vary on;
    gzip_proxied any;
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        application/xml+rss
        image/svg+xml;
}

gzip_min_length 256 überspringt Dateien unter 256 Bytes. Das Komprimieren winziger Dateien kann eine Ausgabe erzeugen, die größer ist als die Eingabe, wegen der gzip-Header. gzip_vary on fügt einen Vary: Accept-Encoding-Header hinzu, damit Caches komprimierte und unkomprimierte Versionen getrennt speichern. gzip_proxied any komprimiert Antworten auch dann, wenn der Request über einen Proxy kam.

Brotli

Brotli liefert 15-25 % bessere Kompression als gzip bei Text-Assets. Es wird von allen modernen Browsern unterstützt. Unter Ubuntu 24.04 mit dem Nginx-Paket der Distribution installieren Sie das Modul direkt:

apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static

Unter Debian 12 oder bei Verwendung von Nginx Mainline von nginx.org ist das Brotli-Modul nicht enthalten. Sie müssen es als dynamisches Modul kompilieren oder ein Drittanbieter-Repository verwenden. Das ngx_brotli-Repository enthält die Build-Anleitung.

Nach dem Laden des Moduls konfigurieren Sie es:

http {
    brotli on;
    brotli_comp_level 4;
    brotli_static on;
    brotli_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        image/svg+xml;
}

brotli_static on liefert vorkomprimierte .br-Dateien aus, falls vorhanden. Das erlaubt Ihnen, Assets beim Build mit einer höheren Kompressionsstufe (z.B. 11) zu komprimieren, ohne die CPU-Kosten zur Laufzeit zu zahlen.

brotli_comp_level 4 ist der Sweet Spot für dynamische Kompression. Anders als bei gzip sind die Brotli-Stufen 1-4 schnell. Stufen ab 5 werden deutlich langsamer.

Kompressionsvergleich

Content-Typ gzip Stufe 5 Brotli Stufe 4 Gewinner
HTML 72 % 78 % Brotli
CSS 80 % 85 % Brotli
JavaScript 75 % 82 % Brotli
JSON 78 % 83 % Brotli

Die Werte stellen die eingesparten Bytes relativ zum Original dar. Brotli gewinnt durchgehend mit 5-8 Prozentpunkten Vorsprung.

Beide Module können gleichzeitig laufen. Nginx liefert Brotli an Clients, die Accept-Encoding: br signalisieren, und fällt für den Rest auf gzip zurück.

Wie optimieren Sie TLS- und HTTP/2-Performance in Nginx?

TLS fügt Latenz durch Handshakes und Schlüsselaustausch hinzu. Session-Caching, OCSP-Stapling und TLS 1.3 minimieren diesen Overhead. HTTP/2 multiplext Requests über eine einzelne Verbindung und beseitigt Head-of-Line-Blocking auf HTTP-Ebene.

HTTP/2

Seit Nginx 1.25.1 ist der http2-Parameter in der listen-Direktive veraltet. Verwenden Sie stattdessen die http2-Direktive:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    #...
}

TLS-Performance

http {
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    resolver 127.0.0.53 valid=300s;
    resolver_timeout 5s;
}

ssl_session_cache shared:SSL:10m speichert TLS-Sitzungsparameter in einer 10 MB großen Shared-Memory-Zone. Ein Megabyte fasst etwa 4.000 Sitzungen. Wiederkehrende Clients überspringen den vollständigen TLS-Handshake und nehmen mit einer deutlich günstigeren Operation wieder auf.

ssl_session_tickets off ist die sicherere Standardeinstellung. Session-Tickets verwenden einen symmetrischen Schlüssel, der bei Kompromittierung alle vergangenen Sitzungen entschlüsselt (keine Forward Secrecy). Wenn Sie Tickets für Multi-Server-Setups benötigen, rotieren Sie die Schlüssel häufig.

ssl_stapling on lässt Nginx die OCSP-Antwort Ihrer CA abrufen und cachen und sie dann in den TLS-Handshake einbetten. Der Client muss die CA nicht separat kontaktieren. Das spart 100-300 ms bei der ersten Verbindung.

ssl_prefer_server_ciphers off ist korrekt für TLS 1.3, wo Client und Server Cipher anders aushandeln. Für TLS-1.2-Abwärtskompatibilität sind die ausgewählten Cipher weiterhin relevant, aber die TLS-1.3-Cipher-Suites sind alle stark.

Für die vollständige TLS- und Let's-Encrypt-Einrichtung siehe die Anleitung zu TLS und Let's Encrypt mit Nginx.

Welche Linux-Kernel-Parameter verbessern die Nginx-Performance?

Vier Kernel-Parameter beschränken Nginx bei der Verarbeitung hoher Verbindungszahlen. Die Standardwerte sind konservativ für einen Allzweckserver. Das Anpassen entfernt Engpässe auf OS-Ebene.

Parameter Standard Empfohlen Warum
net.core.somaxconn 4096 65535 Maximale Listen-Backlog-Warteschlange. Niedrige Werte verursachen Verbindungsabbrüche bei Lastspitzen.
fs.file-max ~100000 500000 Systemweites Dateideskriptor-Limit. Jede Verbindung ist ein Dateideskriptor.
net.ipv4.tcp_tw_reuse 0 1 Wiederverwendung von TIME_WAIT-Sockets für neue Verbindungen. Beschleunigt das Verbindungsrecycling.
net.ipv4.tcp_fastopen 0 3 Aktiviert TCP Fast Open für Client und Server. Spart einen Roundtrip bei neuen Verbindungen.
net.ipv4.ip_local_port_range 32768 60999 1024 65535 Erweitert den Bereich ephemerer Ports für ausgehende Verbindungen (Proxy/Upstream).
net.core.netdev_max_backlog 1000 16384 Warteschlangenlänge für eingehende Pakete, wenn das Interface schneller empfängt als der Kernel verarbeitet.

Live anwenden ohne Neustart:

sysctl -w net.core.somaxconn=65535
sysctl -w fs.file-max=500000
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fastopen=3
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.core.netdev_max_backlog=16384

Persistent über Neustarts hinweg:

cat > /etc/sysctl.d/99-nginx-tuning.conf << 'EOF'
net.core.somaxconn = 65535
fs.file-max = 500000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fastopen = 3
net.ipv4.ip_local_port_range = 1024 65535
net.core.netdev_max_backlog = 16384
EOF
sysctl -p /etc/sysctl.d/99-nginx-tuning.conf
net.core.somaxconn = 65535
fs.file-max = 500000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fastopen = 3
net.ipv4.ip_local_port_range = 1024 65535
net.core.netdev_max_backlog = 16384

Erhöhen Sie auch das Dateideskriptor-Limit pro Prozess für die Nginx-Systemd-Unit. Erstellen Sie ein Override:

mkdir -p /etc/systemd/system/nginx.service.d
cat > /etc/systemd/system/nginx.service.d/limits.conf << 'EOF'
[Service]
LimitNOFILE=65535
EOF
systemctl daemon-reload
systemctl restart nginx
cat /proc/$(pgrep -f 'nginx: master')/limits | grep "open files"
Max open files            65535                65535                files

Wie optimieren Sie die Access-Log-Performance?

Eine Log-Zeile pro Request zu schreiben verbraucht Festplatten-I/O. Auf Servern mit hohem Traffic kann das Access-Logging zum Engpass werden. Gepuffertes Logging schreibt in Stapeln auf die Festplatte.

http {
    access_log /var/log/nginx/access.log combined buffer=64k flush=5s;
}

buffer=64k sammelt Log-Einträge in einem 64 KB großen Speicherpuffer. flush=5s schreibt den Puffer mindestens alle 5 Sekunden auf die Festplatte, auch wenn er nicht voll ist. Das tauscht ein paar Sekunden Log-Verzögerung gegen deutlich weniger Festplatten-I/O.

Wenn Sie keine Access-Logs für statische Assets (Bilder, CSS, JS) brauchen, deaktivieren Sie sie pro Location wie im Caching-Abschnitt oben gezeigt.

Wie viel schneller ist ein getuntes Nginx?

Führen Sie denselben wrk-Benchmark nach dem Anwenden aller Änderungen durch. Testen Sie von derselben Maschine, mit denselben Parametern:

wrk -t4 -c200 -d30s https://your-server.example.com/
Running 30s test @ https://your-server.example.com/
  4 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.21ms    2.34ms  42.56ms   81.23%
    Req/Sec     9.78k   478.12    11.42k    68.75%
  1171200 requests in 30.02s, 4.56GB read
Requests/sec:  39013.66
Transfer/sec:    155.61MB

Vorher vs. Nachher

Metrik Vorher Nachher Veränderung
Requests/sec 16.442 39.014 +137 %
Durchschnittl. Latenz 12,34 ms 5,21 ms -58 %
Max. Latenz 89,12 ms 42,56 ms -52 %
Transfer/sec 65,52 MB 155,61 MB +137 %

Diese Zahlen stammen von einem Virtua Cloud VPS mit 4 vCPUs, 8 GB RAM unter Debian 12 mit Nginx Mainline, der eine statische HTML-Seite mit CSS- und JavaScript-Assets ausliefert. Ihre Ergebnisse variieren je nach Workload, Netzwerkbedingungen und ob Sie zu einem Backend proxyen.

Die größten Gewinne kommen von Kernel-Sysctl (beseitigt OS-Engpässe), Worker/Connection-Tuning (nutzt alle verfügbare CPU) und Kompression (reduziert Bytes auf der Leitung). TLS-Session-Caching und HTTP/2 haben einen kleineren, aber messbaren Effekt, besonders auf die Latenz bei der ersten Verbindung.

Vollständige getunete Konfiguration

Vollständige /etc/nginx/nginx.conf mit allen Tuning-Einstellungen:

user www-data;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 8192;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # TCP-Optimierung
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # Keepalive
    keepalive_timeout 65;
    keepalive_requests 1000;

    # Buffer
    proxy_buffer_size 16k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    client_body_buffer_size 16k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    # Datei-Cache
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # Gzip
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_vary on;
    gzip_proxied any;
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        application/xml+rss
        image/svg+xml;

    # Brotli (falls Modul installiert)
    # brotli on;
    # brotli_comp_level 4;
    # brotli_static on;
    # brotli_types text/plain text/css text/javascript
    #     application/javascript application/json application/xml
    #     image/svg+xml;

    # TLS
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;

    # Logging
    access_log /var/log/nginx/access.log combined buffer=64k flush=5s;
    error_log /var/log/nginx/error.log warn;

    # Version verbergen
    server_tokens off;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

server_tokens off verbirgt die Nginx-Version in Response-Headern und Fehlerseiten. Versionspreisgabe hilft Angreifern, bekannte Schwachstellen gezielt auszunutzen.

Etwas funktioniert nicht?

Prüfen Sie zuerst das Error-Log:

journalctl -u nginx -f

Häufige Probleme nach dem Tuning:

  • "too many open files" im Error-Log: worker_rlimit_nofile ist niedriger als worker_connections, oder das Systemd-LimitNOFILE ist nicht gesetzt. Prüfen Sie beides.
  • "could not build optimal types_hash": Erhöhen Sie types_hash_max_size auf 4096 im http-Block.
  • Brotli-Modul lädt nicht: Führen Sie nginx -V 2>&1 | grep brotli aus, um zu prüfen, ob das Modul einkompiliert ist. Bei dynamischen Modulen prüfen Sie, ob load_module-Direktiven am Anfang von nginx.conf stehen.
  • OCSP-Stapling funktioniert nicht: Der erste Request nach dem Start von Nginx hat keine Stapled-Antwort. Testen Sie mit openssl s_client -connect your-server:443 -status < /dev/null 2>&1 | grep -A 2 "OCSP Response". Wenn "no response sent" erscheint, prüfen Sie, ob ssl_trusted_certificate auf die vollständige Chain zeigt und resolver gesetzt ist.
  • wrk zeigt keine Verbesserung: Stellen Sie sicher, dass Sie von einer anderen Maschine testen. Bei Tests über das Internet dominiert die Netzwerklatenz und überdeckt serverseitige Gewinne. Testen Sie von einem VPS im selben Rechenzentrum für genaue Werte.

Copyright 2026 Virtua.Cloud. Alle Rechte vorbehalten. Dieser Inhalt ist ein Originalwerk des Virtua.Cloud-Teams. Vervielfältigung, Wiederveröffentlichung oder Weiterverbreitung ohne schriftliche Genehmigung ist untersagt.