Nginx-Konfigurationsdatei: Aufbau und Struktur erklärt
Eine vollständige Anleitung zum Aufbau der Nginx-Konfigurationsdateien: Verzeichnisstruktur, verschachtelte Kontexte, Include-Direktiven und die Vererbungsregeln, die in der Praxis oft zu Fehlern führen.
Sie haben Nginx installiert. Sie haben /etc/nginx/nginx.conf geöffnet und eine Datei vorgefunden, die andere Dateien einbindet, die wiederum weitere Dateien einbinden. Manche Direktiven stehen in geschweiften Klammern, andere stehen ganz oben. Bevor Sie mit Server-Blöcken, SSL oder Reverse Proxies anfangen, brauchen Sie die Übersichtskarte.
Dieser Artikel liefert genau das. Keine Rezepte. Nur das mentale Modell, wie die Nginx-Konfiguration funktioniert, damit Sie jede Konfiguration lesen und anpassen können.
Wo liegen die Nginx-Konfigurationsdateien?
Unter Debian 12 und Ubuntu 24.04 installiert das apt-Paket alles unter /etc/nginx/. So sieht das Verzeichnis nach einer frischen Installation aus:
/etc/nginx/
├── nginx.conf # Main config entry point
├── mime.types # Maps file extensions to MIME types
├── conf.d/ # Drop-in config files (*.conf auto-included)
├── sites-available/ # All virtual host config files
│ └── default # Default server block
├── sites-enabled/ # Symlinks to active virtual hosts
│ └── default -> ../sites-available/default
├── snippets/ # Reusable config fragments
│ └── fastcgi-php.conf
├── modules-available/ # Available dynamic module configs
├── modules-enabled/ # Symlinks to loaded modules
├── fastcgi.conf # FastCGI directive defaults
├── fastcgi_params # FastCGI parameter mappings
├── proxy_params # Proxy header defaults
├── scgi_params # SCGI parameter mappings
├── uwsgi_params # uWSGI parameter mappings
├── koi-utf # Character set mapping files
├── koi-win
└── win-utf
Sie können das auf Ihrem eigenen Server prüfen:
ls -la /etc/nginx/
Die Datei, die Sie am häufigsten bearbeiten, ist nicht nginx.conf selbst. Üblicherweise ist es eine Datei in sites-available/ oder conf.d/. Die Hauptdatei nginx.conf setzt globale Standardwerte und bindet diese Dateien über include-Direktiven ein.
Wie sind die Nginx-Konfigurationsdateien aufgebaut?
Die Nginx-Konfiguration verwendet einen Baum aus verschachtelten Kontexten (Contexts). Jeder Kontext ist eine Blockdirektive in geschweiften Klammern. Direktiven innerhalb eines Kontexts gelten nur in diesem Gültigkeitsbereich.
Die Hierarchie sieht so aus:
main (top level, outside any braces)
├── events { }
└── http { }
└── server { }
└── location { }
Jede Direktive in der Konfiguration lebt auf einer dieser Ebenen. Der Main-Kontext ist die Datei selbst. Alles andere ist darin verschachtelt.
Was steuert der Main-Kontext?
Der Main-Kontext umfasst alles außerhalb von Blockdirektiven in nginx.conf. Er steuert prozessweite Einstellungen, die die gesamte Nginx-Instanz betreffen.
Wichtige Direktiven auf dieser Ebene:
| Direktive | Zweck | Typischer Wert |
|---|---|---|
user |
Betriebssystem-Benutzer für die Worker-Prozesse | www-data |
worker_processes |
Anzahl der Worker-Prozesse | auto (entspricht der Anzahl CPU-Kerne) |
pid |
Pfad zur PID-Datei | /run/nginx.pid |
error_log |
Globaler Fehlerlog-Pfad und -Level | /var/log/nginx/error.log |
include |
Modulkonfigurationen laden | /etc/nginx/modules-enabled/*.conf |
Hier ist der Main-Kontext aus der Standard-nginx.conf von Debian 12:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
Diese fünf Zeilen werden vor allem anderen ausgeführt. Sie legen fest, unter welchem Benutzer Nginx läuft, wie viele Worker gestartet werden und wohin Fehler geschrieben werden.
Was gehört in den Events-Block?
Der events-Block konfiguriert, wie Nginx Verbindungen auf Betriebssystemebene verwaltet. Er befindet sich im Main-Kontext.
events {
worker_connections 768;
# multi_accept on;
}
worker_connections legt die maximale Anzahl gleichzeitiger Verbindungen pro Worker-Prozess fest. Mit worker_processes auto auf einem 4-Kern-Rechner erhalten Sie 4 x 768 = 3.072 gleichzeitige Verbindungen. Der Standardwert im Nginx-Quellcode ist 512, Debian setzt ihn auf 768.
Nginx Performance-Tuning auf einem VPS
Wofür ist der HTTP-Kontext?
Der http-Block enthält die gesamte Konfiguration für die HTTP-Verarbeitung. Jeder server-Block lebt darin. Direktiven, die Sie hier platzieren, gelten für alle virtuellen Hosts, sofern kein server- oder location-Block sie überschreibt.
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Beachten Sie server_tokens off; am Anfang. Diese Direktive verbirgt die Nginx-Versionsnummer in den Response-Headern. Die Offenlegung der Version hilft Angreifern, bekannte Schwachstellen gezielt auszunutzen. Die Debian-Standardkonfiguration enthält diese Zeile nicht. Fügen Sie sie hinzu.
Die beiden include-Zeilen am Ende binden Ihre eigentlichen Website-Konfigurationen ein. Im folgenden Abschnitt behandeln wir include im Detail.
Wie funktionieren Server-Blöcke?
Ein server-Block definiert einen virtuellen Host (Virtual Host). Er lebt innerhalb des http-Kontexts. Jeder server-Block lauscht auf einer Adress-/Port-Kombination und ordnet Anfragen anhand des Host-Headers zu.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Wenn eine Anfrage eintrifft, wählt Nginx den server-Block, indem es server_name mit dem Host-Header abgleicht. Wenn kein Block passt, verwendet Nginx den default_server:
listen 80 default_server;
Üblicherweise erstellen Sie pro Domain eine Datei in sites-available/, die jeweils einen server-Block enthält (oder zwei, wenn Sie sowohl HTTP als auch HTTPS verwenden).
Nginx Server Blocks: Mehrere Domains auf einem VPS betreiben
Wie gleicht Nginx Location-Blöcke ab?
Ein location-Block legt fest, wie Nginx Anfragen für bestimmte URI-Muster verarbeitet. Er befindet sich innerhalb eines server-Blocks (oder innerhalb eines anderen location-Blocks).
Nginx wertet Location-Blöcke in einer bestimmten Reihenfolge aus:
| Modifier | Typ | Beispiel | Verhalten |
|---|---|---|---|
= |
Exakter Treffer | location = / |
Passt nur auf /. Suche wird sofort beendet. |
^~ |
Priorisierter Prefix | location ^~ /images/ |
Passt auf den Prefix. Überspringt Regex-Prüfungen. |
~ |
Regex (Groß-/Kleinschreibung beachten) | location ~ \.php$ |
Erster Regex-Treffer gewinnt. |
~* |
Regex (Groß-/Kleinschreibung ignorieren) | location ~* \.(jpg|png)$ |
Erster Regex-Treffer gewinnt. |
| (keiner) | Prefix | location /api/ |
Längster Prefix gewinnt, aber Regex kann überschreiben. |
Der Matching-Algorithmus:
- Nginx prüft alle Prefix-Locations und merkt sich den längsten Treffer.
- Wenn dieser Treffer
=oder^~verwendet, wird gestoppt und dieser verwendet. - Andernfalls werden Regex-Locations in der Reihenfolge ihres Auftretens in der Konfigurationsdatei geprüft.
- Der erste Regex-Treffer gewinnt. Wenn kein Regex passt, wird der längste Prefix aus Schritt 1 verwendet.
Das bedeutet: Die Reihenfolge der Prefix-Locations in der Konfigurationsdatei spielt keine Rolle. Aber die Reihenfolge der Regex-Locations ist entscheidend.
Wie funktioniert die Include-Direktive?
Die include-Direktive fügt den Inhalt einer anderen Datei (oder aller Dateien, die einem Glob-Muster entsprechen) an der aktuellen Position in die Konfiguration ein. Nginx löst sie beim Laden der Konfiguration auf, bevor die Konfiguration als Ganzes geparst wird.
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
Der Glob *.conf passt auf alle Dateien mit der Endung .conf in diesem Verzeichnis. Der Glob * passt auf alles. Beide Muster sind gängig.
Die include-Direktive funktioniert in jedem Kontext. Sie können sie innerhalb von http-, server- oder location-Blöcken verwenden:
server {
listen 443 ssl;
include snippets/ssl-params.conf;
}
So funktioniert das snippets/-Verzeichnis. Sie schreiben ein wiederverwendbares Fragment einmal und binden es überall dort ein, wo Sie es benötigen.
Ein Punkt, auf den Sie achten sollten: Nginx startet nicht, wenn ein include-Pfad ohne Glob auf eine nicht vorhandene Datei verweist. Wenn Sie include /etc/nginx/conf.d/*.conf; schreiben und das Verzeichnis leer ist, startet Nginx problemlos (Globs dürfen auf nichts passen). Aber include /etc/nginx/ssl.conf; schlägt fehl, wenn diese Datei nicht existiert.
Was ist der Unterschied zwischen sites-available, sites-enabled und conf.d?
Diese drei Verzeichnisse dienen unterschiedlichen Zwecken. Debian und Ubuntu verwenden alle drei.
| Verzeichnis | Zweck | Wie Nginx es liest | Wann verwenden |
|---|---|---|---|
sites-available/ |
Speichert alle Virtual-Host-Konfigurationen | Wird nicht direkt gelesen | Immer. Eine Datei pro Domain. |
sites-enabled/ |
Enthält Symlinks zu aktiven Konfigurationen | Eingebunden über include /etc/nginx/sites-enabled/*; |
Symlink erstellen, um eine Website zu aktivieren. |
conf.d/ |
Ergänzende Konfigurationsfragmente | Eingebunden über include /etc/nginx/conf.d/*.conf; |
Globale HTTP-Einstellungen, Upstream-Blöcke, Maps. |
Das Muster sites-available / sites-enabled ermöglicht es, eine Website zu deaktivieren, ohne ihre Konfiguration zu löschen. Um eine Website zu aktivieren:
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
Um sie zu deaktivieren:
rm /etc/nginx/sites-enabled/example.com
Dann neu laden:
sudo nginx -t && sudo systemctl reload nginx
Führen Sie immer nginx -t vor dem Neuladen aus. Das validiert die Konfiguration, ohne den laufenden Datenverkehr zu beeinträchtigen.
Das Verzeichnis conf.d/ ist einfacher. Jede .conf-Datei darin wird automatisch geladen. Keine Symlinks nötig. Manche Administratoren bevorzugen conf.d/ wegen der Einfachheit und verzichten komplett auf sites-available/sites-enabled. Beide Ansätze funktionieren. Wählen Sie einen und bleiben Sie konsistent.
Ein Fallstrick: Wenn Sie sowohl conf.d/ als auch sites-enabled/ verwenden, stellen Sie sicher, dass Sie keine widersprüchlichen server-Blöcke an beiden Stellen definieren. Nginx lädt beide, und das Ergebnis hängt von den Regeln zur Direktiven-Zusammenführung und dem server_name-Matching ab.
Wie funktioniert die Direktiven-Vererbung in Nginx?
Nginx reicht Direktiven von übergeordneten Kontexten an untergeordnete Kontexte weiter. Das ist der Teil, den die meisten Leute falsch verstehen, und die Ursache subtiler Produktionsfehler.
Es gibt drei Typen von Direktiven, und jeder vererbt anders.
Normale Direktiven
Normale Direktiven halten einen einzelnen Wert. Wenn ein untergeordneter Kontext dieselbe Direktive definiert, ersetzt er den Wert des übergeordneten Kontexts vollständig. Wenn der untergeordnete Kontext sie nicht definiert, wird der Wert des übergeordneten Kontexts vererbt.
Beispiel: root ist eine normale Direktive.
http {
root /var/www/default;
server {
server_name example.com;
# root is inherited: /var/www/default
location /app {
root /var/www/app;
# root is overridden: /var/www/app
}
location /blog {
# root is inherited: /var/www/default
}
}
}
Weitere normale Direktiven: index, access_log (bei einmaliger Verwendung), error_log, client_max_body_size.
Array-Direktiven
Array-Direktiven können mehrfach im selben Kontext erscheinen, um Werte zu akkumulieren. Aber sobald ein untergeordneter Kontext auch nur eine Instanz definiert, werden alle Werte des übergeordneten Kontexts ersetzt. Nicht zusammengeführt. Ersetzt.
add_header ist die bekannteste Array-Direktive. Dieses Verhalten verursacht einen weitverbreiteten Produktionsfehler.
Was passiert, wenn Sie Header sowohl im HTTP- als auch im Location-Block setzen?
Wenn Sie add_header im http-Kontext definieren und dann ein anderes add_header in einem location-Block setzen, löscht der Location-Block alle Header aus dem HTTP-Kontext. Nicht nur den einen, den Sie überschreiben. Alle.
http {
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
server {
server_name example.com;
location /api/ {
add_header X-Custom "api-response";
# X-Frame-Options is GONE
# X-Content-Type-Options is GONE
# Only X-Custom is sent
}
}
}
Um das auf Ihrem Server zu prüfen:
curl -I https://example.com/api/
Prüfen Sie die Response-Header. Wenn Ihre Sicherheitsheader bei /api/-Antworten fehlen, aber auf anderen Pfaden vorhanden sind, ist das die Ursache.
Die Lösung: Alle Header im untergeordneten Kontext wiederholen.
location /api/ {
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-Custom "api-response";
}
Oder ein Snippet verwenden:
# /etc/nginx/snippets/security-headers.conf
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=63072000" always;
location /api/ {
include snippets/security-headers.conf;
add_header X-Custom "api-response";
}
Hinweis: Ab Nginx 1.29.3 gibt es add_header_inherit merge;, das dieses Verhalten ändert. Mit merge fügen untergeordnete Kontexte ihre Header an die des übergeordneten Kontexts an, anstatt sie zu ersetzen. Wenn Sie Nginx 1.28.x verwenden (die aktuelle Stable-Version, Stand März 2026), steht Ihnen das noch nicht zur Verfügung.
Dasselbe Löschverhalten gilt für proxy_set_header. Wenn Sie ein beliebiges proxy_set_header in einem location-Block definieren, gehen alle proxy_set_header-Direktiven aus dem server- oder http-Kontext verloren. Die offizielle Dokumentation formuliert es eindeutig: "These directives are inherited from the previous configuration level if and only if there are no proxy_set_header directives defined on the current level."
server {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /api/ {
proxy_set_header X-Request-ID $request_id;
# Host, X-Real-IP, X-Forwarded-For are all GONE
proxy_pass http://backend;
}
}
Die Lösung ist dieselbe: Alle Header im Location-Block wiederholen oder ein Include-Snippet verwenden.
Action-Direktiven
Action-Direktiven wie rewrite und return werden nicht in verschachtelte Kontexte vererbt. Sie werden nur in dem Kontext ausgeführt, in dem sie definiert sind.
server {
rewrite ^/old/(.*)$ /new/$1 permanent;
location /app {
# The rewrite above does NOT apply here
# Requests matching /app are handled by this location
}
}
Die Direktive try_files hat einen verwandten Fallstrick. Wenn sie im server-Kontext platziert wird, erstellt Nginx eine implizite Pseudo-Location mit der niedrigstmöglichen Priorität. Wenn ein regulärer location-Block die Anfrage trifft, wird try_files auf Server-Ebene nie ausgeführt:
server {
try_files $uri /index.php; # Never runs for /app/* requests
location /app { } # This catches them first
}
Platzieren Sie try_files immer innerhalb eines spezifischen location-Blocks.
Wie prüfen Sie die effektive Nginx-Konfiguration?
Zwei Befehle helfen Ihnen zu verstehen, was Nginx nach dem Auflösen aller include-Direktiven tatsächlich sieht.
Konfiguration auf Syntaxfehler prüfen:
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Führen Sie das immer vor dem Neuladen aus. Bei einem Fehler nennt Nginx die Datei und Zeilennummer.
Gesamte zusammengeführte Konfiguration ausgeben:
sudo nginx -T
Dieser Befehl gibt die gesamte effektive Konfiguration aus, mit allen aufgelösten und inline expandierten Includes. Leiten Sie die Ausgabe an less weiter:
sudo nginx -T | less
Oder suchen Sie nach einer bestimmten Direktive:
sudo nginx -T | grep -n "add_header"
Das zeigt jede add_header-Direktive über alle eingebundenen Dateien hinweg, mit Zeilennummern in der zusammengeführten Ausgabe. Verwenden Sie das beim Debugging von Vererbungsproblemen. Wenn ein Header im HTTP-Block erscheint, aber nicht in einem Location-Block, und Sie kein add_header in diesem Location-Block sehen, wird der Header vererbt. Wenn Sie ein anderes add_header im Location-Block sehen, werden alle übergeordneten Header gelöscht.
Verwenden Sie nginx -T, wann immer Konfigurationsänderungen sich nicht wie erwartet verhalten.
Kurzreferenz: das Gesamtbild
/etc/nginx/nginx.conf
│
├─ main context (process-level: user, worker_processes, pid)
│
├─ events { } (connection handling: worker_connections)
│
└─ http { } (all HTTP config)
│
├─ include conf.d/*.conf (global HTTP settings, upstreams, maps)
├─ include sites-enabled/* (virtual host configs)
│
└─ server { } (one per domain/port)
│
├─ listen, server_name (routing)
├─ root, index (defaults for this host)
│
└─ location { } (URI pattern matching)
├─ try_files, root (per-path behavior)
└─ proxy_pass (reverse proxy target)
Inheritance: parent -> child (down only)
Normal directives: child overrides parent
Array directives: child REPLACES ALL parent values
Action directives: no inheritance
Bereit, es selbst auszuprobieren?
Hosten Sie Ihre Webanwendungen auf einem zuverlassigen VPS. →