Nginx-Konfigurationstests: Reibungslose Bereitstellungen mit wichtigen Befehlen sicherstellen
Verwenden Sie nginx -t, nginx -T und sichere Neuladegewohnheiten, um Nginx-Konfigurationsfehler zu erkennen, bevor sie den Datenverkehr beeinträchtigen.
Nginx-Konfigurationstests: Reibungslose Bereitstellungen mit wichtigen Befehlen sicherstellen
Nginx-Konfigurationstests sind eine dieser Gewohnheiten, die zu unbedeutend erscheinen, bis sie Sie vor einem fehlgeschlagenen Neuladen bewahren. Ein fehlendes Semikolon, ein falscher Include-Pfad oder eine Direktive aus einem Modul, das Sie nicht haben, können Nginx daran hindern, eine neue Konfiguration zu akzeptieren. Auf einem Produktions-Reverse-Proxy ist das kein kleiner Fehler.
Der Kernbefehl ist einfach:
sudo nginx -t
Führen Sie ihn vor jedem Neuladen aus. Führen Sie ihn nach dem Bearbeiten eines Server-Blocks aus. Führen Sie ihn in CI aus, wenn Ihr Team Nginx-Konfigurationen in Git speichert. Der Befehl parst die Konfiguration und meldet, ob die Syntax gültig ist. Er beweist nicht, dass Ihre Routing-Logik korrekt ist, Ihr TLS-Zertifikat für jeden Hostnamen gültig ist oder Ihre Upstream-App gesund ist. Er fängt die Art von Fehlern, die Nginx erkennen kann, bevor es die Konfiguration anwendet.
Was nginx -t prüft
nginx -t weist Nginx an, die Konfiguration zu testen. Es liest die Hauptkonfigurationsdatei, folgt include-Direktiven, parst Direktiven und Blöcke und prüft auf viele Datei-/Pfadprobleme. Ein erfolgreicher Lauf sieht normalerweise so aus:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Ein fehlgeschlagener Lauf zeigt auf eine Datei und Zeilennummer:
nginx: [emerg] unexpected "}" in /etc/nginx/conf.d/api.conf:18
nginx: configuration file /etc/nginx/nginx.conf test failed
Die Zeilennummer gibt an, wo der Parser das Problem bemerkt hat, nicht unbedingt, wo Sie den Fehler gemacht haben. Wenn Nginx meldet, dass eine unerwartete } in Zeile 18 auftritt, überprüfen Sie die Zeilen darüber auf ein fehlendes Semikolon oder einen nicht geschlossenen Block.
Verwenden Sie sudo, wenn die Konfigurationsdateien, Zertifikatsdateien oder eingebundenen Snippets nur für root lesbar sind:
sudo nginx -t
Ohne die richtigen Berechtigungen kann Ihr Test fehlschlagen, obwohl die Syntax in Ordnung ist.
Verwenden Sie nginx -T, wenn Includes die Konfiguration schwer lesbar machen
Viele Nginx-Setups verteilen die Konfiguration auf /etc/nginx/nginx.conf, conf.d/*.conf, sites-enabled/* und gemeinsame Snippets. Das ist gut für die Wartbarkeit, kann aber das Debuggen erschweren.
nginx -T testet die Konfiguration und gibt die vollständig geparste Konfiguration auf stdout aus:
sudo nginx -T
Dies ist nützlich, wenn Sie Fragen beantworten müssen wie:
- Welche Datei definiert eigentlich diesen Server-Block?
- Hat mein
include-Muster eine Backup-Datei aufgenommen? - Wird diese Direktive auf
http-,server- oderlocation-Ebene gesetzt? - Welcher doppelte
server_name-Block gewinnt?
Seien Sie vorsichtig beim Teilen der nginx -T-Ausgabe. Sie kann Zertifikatspfade, interne Hostnamen, Upstream-Namen, Header oder Kommentare mit sensiblen Kontext enthalten. Für ein Ticket schwärzen Sie vor dem Einfügen.
Testen Sie eine nicht standardmäßige Konfigurationsdatei mit -c
Wenn Sie eine Konfiguration in einem Staging-Pfad erstellen, verwenden Sie -c:
sudo nginx -t -c /home/deploy/nginx-staging/nginx.conf
Dies teilt Nginx mit, welche Hauptkonfigurationsdatei zu testen ist. Relative Pfade innerhalb dieser Konfiguration können sich je nach Präfixeinstellungen unterschiedlich verhalten. Halten Sie Staging-Tests daher nach Möglichkeit nahe am Produktionslayout.
Sie können auch die Kompilierungszeit-Pfade und Module überprüfen mit:
nginx -V
Die Ausgabe geht auf vielen Systemen nach stderr, was überrascht, wenn man die Ausgabe umleitet. Sie zeigt die Nginx-Version und Build-Optionen, einschließlich Modulunterstützung und Standardpfade. Das ist wichtig, wenn eine Konfiguration Direktiven von Modulen wie http_v2, realip, stub_status oder Stream-Proxying verwendet.
Neuladen, nicht einfach neu starten
Sobald der Test bestanden ist, laden Sie Nginx neu:
sudo systemctl reload nginx
Ein Neuladen fordert den Master-Prozess auf, die neue Konfiguration zu lesen und neue Worker zu starten, während alte Worker bestehende Anfragen beenden. Das ist der normale Weg für Konfigurationsänderungen.
Ein Neustart stoppt und startet den Dienst:
sudo systemctl restart nginx
Verwenden Sie einen Neustart, wenn Sie ihn tatsächlich benötigen, z. B. nach Paketänderungen oder einem Dienstzustandsproblem. Für normale Konfigurationsänderungen ist das Neuladen weniger störend.
Einige systemd-Unit-Dateien führen einen Konfigurationstest als Teil des Neuladens durch. Verlassen Sie sich nicht darauf als Ihr einziges Sicherheitsnetz. Führen Sie zuerst selbst nginx -t aus, damit Sie den Fehler sehen, bevor Sie den laufenden Dienst berühren.
Der native Nginx-Signal-Befehl ist ebenfalls üblich:
sudo nginx -s reload
Auf Servern, die mit systemd verwaltet werden, bevorzuge ich normalerweise systemctl reload nginx, weil es den Dienststatus und die Protokolle in derselben Verwaltungsebene hält.
Ein sicherer Bearbeitungs-Workflow
Für eine normale Server-Block-Änderung verwenden Sie diesen Rhythmus:
sudo cp /etc/nginx/conf.d/api.conf /etc/nginx/conf.d/api.conf.bak.$(date +%Y%m%d%H%M%S)
sudoedit /etc/nginx/conf.d/api.conf
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx --no-pager
Wenn Ihre Konfiguration in Git ist, committen Sie die Änderung, anstatt zufällige Backup-Dateien für immer zu behalten. Der obige Backup-Befehl ist nützlich für kleine, nicht verwaltete Server, aber kein Ersatz für die Versionskontrolle.
Testen Sie nach dem Neuladen die tatsächliche Route:
curl -I https://example.com/api/health
curl -I -H 'Host: example.com' http://127.0.0.1/
nginx -t kann Ihnen sagen, dass die Konfiguration parst. curl sagt Ihnen, ob die Site sich so verhält, wie Sie es beabsichtigt haben.
Häufige Fehlermeldungen und was sie normalerweise bedeuten
Ein fehlendes Semikolon sieht oft so aus:
nginx: [emerg] invalid number of arguments in "proxy_set_header" directive in /etc/nginx/conf.d/app.conf:22
Überprüfen Sie die Direktive in dieser Zeile und der davor. Nginx-Direktiven enden normalerweise mit ;, während Blöcke mit { ... } enden.
Ein falscher Include-Pfad sieht so aus:
nginx: [emerg] open() "/etc/nginx/snippets/security-headers.conf" failed (2: No such file or directory)
Entweder ist der Dateipfad falsch, das Snippet wurde nicht bereitgestellt oder das Include-Muster ist umgebungsspezifisch.
Ein Berechtigungsproblem kann so aussehen:
nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/example.com/fullchain.pem": BIO_new_file() failed
Die Datei fehlt möglicherweise, der Symlink ist defekt oder der Benutzer, der den Test ausführt, kann sie nicht lesen. Zertifikatserneuerungs- und Bereitstellungsskripte sind häufige Orte, an denen dies passiert.
Eine unbekannte Direktive bedeutet eines von drei Dingen: Tippfehler, falscher Kontext oder fehlendes Modul.
nginx: [emerg] unknown directive "proxy_cache_purge"
Vielleicht ist der Direktivenname falsch. Vielleicht gehört es in ein anderes Modul. Vielleicht enthält Ihr Produktions-Nginx-Build nicht das Drittanbieter-Modul, das auf dem Staging existierte. Überprüfen Sie nginx -V, bevor Sie annehmen, dass die Konfiguration portabel ist.
Ein doppelter oder widersprüchlicher Servername kann als Warnung und nicht als harter Fehler erscheinen:
nginx: [warn] conflicting server name "example.com" on 0.0.0.0:80, ignored
Ignorieren Sie Warnungen nicht nur, weil die letzte Zeile besagt, dass der Test erfolgreich war. Eine Warnung kann bedeuten, dass Nginx den Server-Block nicht verwendet, von dem Sie glauben, dass er verwendet wird.
Testen in CI
Wenn die Nginx-Konfiguration in einem Repository lebt, testen Sie sie vor der Bereitstellung. Ein einfacher containerbasierter Check kann die Konfiguration in ein Nginx-Image einbinden und ausführen:
nginx -t -c /etc/nginx/nginx.conf
Der schwierige Teil ist das Abgleichen der Produktionspfade. Wenn Ihre Konfiguration auf /etc/letsencrypt verweist, benötigen lokale Tests Platzhalterdateien oder eine testspezifische Konfiguration. Wenn sie auf Upstream-Hostnamen verweist, benötigt der Syntax-Test nicht, dass der Upstream lebt, aber eingebundene Dateien und Zertifikatsdateien müssen existieren.
Für Teams mit vielen Sites fügen Sie einen Pre-Deploy-Schritt hinzu, der nginx -T ausführt und bereinigte Ausgabe als Artefakt speichert. Wenn ein Neuladen sich seltsam verhält, können Sie die gerenderte Konfiguration des letzten guten Deploys mit der aktuellen vergleichen.
Was Konfigurationstests nicht abdecken können
nginx -t wird Ihnen nicht sagen, dass Ihr neuer location-Block von einem anderen Regex-Location überschattet wird. Es wird nicht wissen, dass Ihre Upstream-App 500er zurückgibt. Es wird nicht beweisen, dass eine Weiterleitungskette sinnvoll oder eine Cache-Regel sicher ist.
Fügen Sie dafür Verhaltensprüfungen hinzu:
curl -I https://example.com/
curl -I https://example.com/old-path
curl -sS https://example.com/api/health
Für TLS-Änderungen überprüfen Sie das Zertifikat aus Client-Sicht:
openssl s_client -connect example.com:443 -servername example.com </dev/null
Für Reverse-Proxy-Änderungen beobachten Sie die Protokolle während und nach dem Neuladen:
sudo tail -f /var/log/nginx/error.log /var/log/nginx/access.log
Nginx-Konfigurationstests sind keine vollständige Bereitstellungsstrategie, aber sie sind das Tor, das jede Strategie enthalten sollte. Verwenden Sie nginx -t für die Syntax, nginx -T für das Debuggen der gerenderten Konfiguration, nginx -V für Build-Details und systemctl reload nginx für normale Änderungen. Überprüfen Sie dann das Verhalten mit echten Anfragen.