So diagnostizieren und beheben Sie Nginx 502 Bad Gateway-Fehler

Beheben Sie Nginx 502-Fehler durch Überprüfung der Fehlerprotokolle, Upstream-Integrität, Socket-Berechtigungen, Proxy-Einstellungen, Timeouts und Firewalls.

So diagnostizieren und beheben Sie Nginx 502 Bad Gateway-Fehler

Nginx ist ein leistungsstarker und beliebter Webserver und Reverse-Proxy, der häufig verwendet wird, um statische Inhalte bereitzustellen, den Datenverkehr zu verteilen und Anfragen an verschiedene vorgelagerte Anwendungsserver wie PHP-FPM, Node.js, Python Gunicorn oder Apache Tomcat weiterzuleiten. Wenn Nginx auf ein Problem bei der Kommunikation mit einem dieser vorgelagerten Server stößt, antwortet es in der Regel mit einem „502 Bad Gateway“-Fehler.

Beginnen Sie mit dem Nginx-Fehlerprotokoll und überprüfen Sie dann, ob der vorgelagerte Prozess läuft, erreichbar ist und antworten darf.

Den Nginx 502 Bad Gateway-Fehler verstehen

Ein 502 Bad Gateway-Fehler zeigt an, dass Nginx, das als Reverse-Proxy fungiert, eine ungültige Antwort von einem vorgelagerten Server erhalten hat. Das bedeutet, dass Nginx erfolgreich eine Verbindung zu einem vorgelagerten Server hergestellt hat, aber entweder keine Antwort, eine unvollständige Antwort oder eine Antwort erhalten hat, die es nicht verstehen konnte. Entscheidend ist, dass das Problem nicht bei Nginx selbst liegt, sondern bei dem Dienst, mit dem Nginx kommunizieren möchte.

Häufige vorgelagerte Server sind:

  • PHP-FPM: Für PHP-Anwendungen (z. B. WordPress, Laravel).
  • Gunicorn/uWSGI: Für Python-Anwendungen (z. B. Django, Flask).
  • Node.js: Für JavaScript-Anwendungen.
  • Apache Tomcat: Für Java-Anwendungen.
  • Andere Webserver: Wie der Apache HTTP-Server, der bestimmte Inhalte bereitstellt.

Der 502-Fehler ist ein entscheidender Hinweis darauf, dass das Backend Ihrer Anwendung nicht richtig funktioniert oder für Nginx nicht erreichbar ist.

Schritt-für-Schritt-Diagnose

Der Schlüssel zur Behebung eines 502-Fehlers ist eine systematische Diagnose. Beginnen Sie mit den wahrscheinlichsten Ursachen und untersuchen Sie dann schrittweise weiter.

1. Überprüfen Sie zuerst die Nginx-Fehlerprotokolle

Ihre Nginx-Fehlerprotokolle sind die primäre Informationsquelle. Sie enthalten oft spezifische Details darüber, warum Nginx nicht mit dem vorgelagerten Server kommunizieren konnte.

  • Speicherort: Normalerweise unter /var/log/nginx/error.log.
  • Befehl: Verwenden Sie tail -f, um die Protokolle in Echtzeit zu überwachen, während Sie versuchen, den Fehler zu reproduzieren.
tail -f /var/log/nginx/error.log

Worauf Sie achten sollten:

  • connect() failed (111: Connection refused): Zeigt an, dass der vorgelagerte Server nicht auf der angegebenen Adresse/dem angegebenen Port lauscht oder eine Firewall die Verbindung blockiert.
  • upstream timed out: Der vorgelagerte Server hat zu lange gebraucht, um zu antworten.
  • upstream prematurely closed connection: Der vorgelagerte Server hat die Verbindung geschlossen, bevor er eine vollständige Antwort gesendet hat.
  • no live upstreams while connecting to upstream: Nginx konnte keine verfügbaren vorgelagerten Server in der Konfiguration finden.

2. Überprüfen Sie den Status des vorgelagerten Servers

Sobald Sie Hinweise aus den Nginx-Fehlerprotokollen haben, überprüfen Sie den Status Ihres vorgelagerten Anwendungsservers.

  • Für PHP-FPM:

    sudo systemctl status php8.2-fpm
    
  • Für Node.js/Python/andere benutzerdefinierte Apps: Überprüfen Sie, ob der Prozess läuft.

    ps aux | grep node
    ps aux | grep gunicorn
    

    Wenn Sie einen Prozessmanager wie PM2 (Node.js) oder Supervisor (allgemein) verwenden, überprüfen Sie dessen Status.

    pm2 status
    sudo supervisorctl status
    

Wenn der Dienst nicht läuft, versuchen Sie, ihn zu starten, und überprüfen Sie seine eigenen Protokolle auf Fehler.

sudo systemctl start php8.2-fpm

3. Überprüfen Sie die Netzwerkkonnektivität zum vorgelagerten Server

Stellen Sie sicher, dass Nginx den vorgelagerten Server auf dem konfigurierten Port oder Socket-Pfad erreichen kann.

  • Für TCP/IP-Verbindungen (z. B. 127.0.0.1:8000): Verwenden Sie telnet oder nc (netcat), um die Port-Konnektivität vom Nginx-Server aus zu testen.

    telnet 127.0.0.1 8000
    nc -vz 127.0.0.1 8000
    

    Eine erfolgreiche Verbindung sollte Connected to 127.0.0.1. oder succeeded! anzeigen. Wenn es hängt oder Connection refused anzeigt, lauscht der vorgelagerte Dienst nicht oder eine Firewall blockiert ihn.

  • Für Unix-Sockets (z. B. unix:/run/php/phpX.X-fpm.sock): Überprüfen Sie, ob die Socket-Datei existiert und die richtigen Berechtigungen hat.

    ls -l /run/php/phpX.X-fpm.sock
    

    Nginx sollte Lese-/Schreibberechtigungen für diese Socket-Datei haben. Der Nginx-Benutzer (z. B. www-data) muss Teil der Gruppe sein, die den Socket besitzt (z. B. www-data oder php-fpm).

Häufige Ursachen und Lösungen

Basierend auf Ihren Diagnoseschritten sind hier die häufigsten Ursachen für 502-Fehler und wie Sie sie beheben können.

1. Vorgelagerter Server läuft nicht oder ist abgestürzt

Ursache: Die Anwendung, an die Nginx proxy weiterleiten soll (z. B. PHP-FPM, Gunicorn, Node.js-App), läuft nicht oder ist abgestürzt.

Lösung: Starten oder neu starten Sie den vorgelagerten Dienst.

# Beispiel für PHP-FPM
sudo systemctl start php8.2-fpm
# Wenn er bereits läuft und Sie einen Absturz vermuten, starten Sie ihn neu:
sudo systemctl restart php8.2-fpm

# Für benutzerdefinierte Anwendungen verwenden Sie deren spezifische Start-/Neustart-Befehle

Tipp: Stellen Sie sicher, dass Ihre vorgelagerten Dienste so konfiguriert sind, dass sie beim Systemstart automatisch starten. Für systemd-Dienste verwenden Sie systemctl enable phpX.X-fpm.

2. Überlastung des vorgelagerten Servers / Ressourcenerschöpfung

Ursache: Der vorgelagerte Server ist überlastet, ihm gehen Speicher, CPU oder Prozesslimits aus, sodass er nicht mehr antwortet oder neue Verbindungen ablehnt.

Symptome: Nginx-Fehlerprotokolle zeigen möglicherweise zeitweise connection refused oder upstream timed out, insbesondere unter Last. Systemüberwachungstools (top, htop, free -h) zeigen eine hohe Ressourcennutzung.

Lösungen:

  • Für PHP-FPM: Passen Sie die PHP-FPM-Pool-Einstellungen in der Konfigurationsdatei an (z. B. /etc/php/X.X/fpm/pool.d/www.conf).

    • pm.max_children: Die maximale Anzahl von Kindern, die gleichzeitig aktiv sein können.
    • pm.start_servers: Die Anzahl der Kinder, die beim Start erstellt werden.
    • pm.min_spare_servers, pm.max_spare_servers: Steuert, wie viele untätige Kinder vorgehalten werden.
    ; Beispiel für dynamische Prozessverwaltung
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 10
    pm.min_spare_servers = 5
    pm.max_spare_servers = 20
    
    • Erhöhen Sie memory_limit in der php.ini, wenn Skripte den Speicher erschöpfen.
  • Für andere Anwendungen: Erhöhen Sie die Anzahl der Worker-Prozesse, Threads oder weisen Sie nach Möglichkeit mehr Speicher zu. Überwachen Sie die spezifischen Metriken Ihrer Anwendung.

  • Nginx-Timeouts: Erhöhen Sie die Nginx-Direktiven proxy_connect_timeout, proxy_send_timeout und proxy_read_timeout in Ihrer Nginx-Konfiguration, aber verstehen Sie, dass dies den Fehler nur verzögert, wenn das Backend wirklich überlastet ist.

    http {
        ...
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        ...
    }
    

3. Falsche vorgelagerte Konfiguration in Nginx

Ursache: Nginx ist so konfiguriert, dass es eine Verbindung zur falschen IP-Adresse, zum falschen Port oder Unix-Socket-Pfad für den vorgelagerten Server herstellt.

Symptome: Nginx-Fehlerprotokolle zeigen sofort nach einer Anfrage connect() failed (111: Connection refused).

Lösung: Überprüfen Sie sorgfältig Ihre Nginx-Serverblock-Konfiguration (/etc/nginx/sites-available/your_site.conf).

  • Für HTTP/HTTPS-Upstreams:

    location /app {
        proxy_pass http://127.0.0.1:8000; # Stellen Sie sicher, dass IP und Port korrekt sind
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
  • Für PHP-FPM über Unix-Socket:

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/phpX.X-fpm.sock; # Überprüfen Sie, ob dieser Pfad genau mit der PHP-FPM-Konfiguration übereinstimmt
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    
  • Für PHP-FPM über TCP/IP:

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000; # Überprüfen Sie IP und Port
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    

Testen Sie nach Änderungen immer Ihre Nginx-Konfiguration und laden Sie Nginx neu/starten Sie es neu:

nginx -t
systemctl reload nginx # Oder restart, wenn -t darauf hinweist

4. PHP-FPM request_terminate_timeout überschritten

Ursache: Ein PHP-Skript benötigt länger für die Ausführung als die Einstellung request_terminate_timeout in PHP-FPM. Nginx wartet auf die Antwort, aber PHP-FPM beendet das Skript, sodass Nginx eine unvollständige Antwort erhält.

Symptome: Nginx-Fehlerprotokolle zeigen möglicherweise upstream timed out oder script timed out. PHP-FPM-Protokolle zeigen möglicherweise child XX exited on signal 9 (SIGKILL).

Lösung:

  • Erhöhen Sie request_terminate_timeout: Finden und passen Sie diese Direktive in Ihrer PHP-FPM-Pool-Konfiguration (www.conf) an. Wenn Sie sie auf 0 setzen, wird das Timeout deaktiviert, was jedoch im Allgemeinen nicht empfohlen wird, da lang laufende Skripte Ressourcen blockieren können.

    request_terminate_timeout = 300 # Erhöhen auf 5 Minuten (300 Sekunden)
    
  • Erhöhen Sie fastcgi_read_timeout in Nginx: Dieses Nginx-Timeout sollte gleich oder größer als request_terminate_timeout sein.

    location ~ \.php$ {
        ...
        fastcgi_read_timeout 300s; # Muss >= PHP-FPM's request_terminate_timeout sein
        ...
    }
    

Warnung: Das Erhöhen von Timeouts kann den 502-Fehler beheben, aber es kann zugrunde liegende Leistungsprobleme überdecken. Die beste langfristige Lösung ist die Optimierung des langsamen PHP-Skripts.

5. Firewall-Probleme

Ursache: Eine Firewall (entweder auf dem Nginx-Server oder auf dem vorgelagerten Server, wenn sie getrennt sind) blockiert Verbindungen zum vorgelagerten Port oder Socket.

Lösung:

  • Firewall-Status überprüfen:

    sudo ufw status # Für UFW (Ubuntu/Debian)
    sudo firewall-cmd --list-all # Für firewalld (CentOS/RHEL)
    sudo iptables -L # Für iptables
    
  • Notwendige Ports öffnen: Stellen Sie sicher, dass der Port, den Nginx für die Verbindung zum vorgelagerten Server verwendet (z. B. 9000 für PHP-FPM über TCP/IP), geöffnet ist.

    sudo ufw allow from 127.0.0.1 to any port 9000 # Erlaube localhost, sich mit 9000 zu verbinden
    sudo firewall-cmd --permanent --add-port=9000/tcp # Für firewalld
    sudo firewall-cmd --reload
    
  • Deaktivieren Sie die Firewall vorübergehend zu Testzwecken nur in einer kontrollierten Umgebung und aktivieren und konfigurieren Sie sie dann ordnungsgemäß wieder.

6. SELinux- oder AppArmor-Interferenz

Ursache: Sicherheitserweiterungen wie SELinux (auf RHEL/CentOS) oder AppArmor (auf Ubuntu/Debian) könnten Nginx daran hindern, auf den vorgelagerten Socket zuzugreifen oder Netzwerkverbindungen herzustellen, selbst wenn Dateiberechtigungen und Firewalls korrekt konfiguriert sind.

Symptome: Protokolle zeigen möglicherweise permission denied oder ähnliche Meldungen, insbesondere in /var/log/audit/audit.log (für SELinux).

Lösung:

  • Überprüfen Sie audit.log:

    sudo grep nginx /var/log/audit/audit.log
    
  • Setzen Sie SELinux vorübergehend in den permissiven Modus: sudo setenforce 0. Wenn der Fehler behoben ist, ist SELinux die Ursache. Sie müssen dann geeignete SELinux-Richtlinien generieren und anwenden (z. B. audit2allow). Denken Sie daran, es wieder in den enforcing-Modus zu setzen (sudo setenforce 1).

  • Überprüfen Sie den AppArmor-Status: sudo aa-status. Wenn AppArmor aktiv ist, müssen Sie möglicherweise das Nginx-Profil anpassen.

7. Große Anfrage-/Antwortkörper (Proxy-Pufferung)

Ursache: Die standardmäßigen Proxy-Puffereinstellungen von Nginx könnten für sehr große Anfrage- oder Antwortkörper zu klein sein, was zu einem vorzeitigen Verbindungsabbruch führt.

Symptome: Nginx-Fehlerprotokolle zeigen möglicherweise upstream prematurely closed connection while reading response header from upstream oder upstream prematurely closed connection while reading response body from upstream.

Lösung: Passen Sie die Nginx-Proxy-Puffer-Direktiven in Ihrem http-, server- oder location-Block an.

http {
    ...
    proxy_buffer_size   128k; # Größe des Puffers für den ersten Teil der Antwort
    proxy_buffers   4 256k; # Anzahl und Größe der Puffer für den Rest der Antwort
    proxy_busy_buffers_size   256k; # Maximale Größe der belegten Puffer
    proxy_temp_file_write_size 256k; # Größe für das Schreiben in temporäre Dateien, wenn die Pufferung überläuft
    ...
}

Hinweis: Diese Einstellungen verbrauchen mehr Speicher. Passen Sie sie vorsichtig an, basierend auf den Ressourcen Ihres Servers und der typischen Größe der Antworten Ihrer Anwendung.

Allgemeine Tipps zur Fehlerbehebung

  • Überprüfen Sie alle relevanten Protokolle: Neben den Nginx-Fehlerprotokollen überprüfen Sie auch die Nginx-Zugriffsprotokolle, die Protokolle der vorgelagerten Anwendung (PHP-FPM, Gunicorn, Node.js-App-Protokolle) und Systemprotokolle (/var/log/syslog, dmesg).
  • Nginx neu starten: Starten Sie Nginx nach Konfigurationsänderungen immer neu, um sicherzustellen, dass sie wirksam werden: systemctl restart nginx.
  • Nginx-Konfiguration testen: Überprüfen Sie vor dem Neustart die Syntax Ihrer Nginx-Konfiguration: nginx -t.
  • Problem isolieren: Versuchen Sie, Nginx zu umgehen und direkt auf die vorgelagerte Anwendung zuzugreifen. Wenn Ihre Node.js-App beispielsweise auf localhost:3000 läuft, verwenden Sie curl http://localhost:3000 von der Befehlszeile des Servers aus. Wenn auch dies fehlschlägt, liegt das Problem definitiv bei Ihrer Anwendung, nicht bei Nginx.
  • Festplattenspeicher überprüfen: Eine volle Festplatte kann verhindern, dass Anwendungen temporäre Dateien oder Protokolle schreiben, was zu Abstürzen oder Fehlern führt. Verwenden Sie df -h, um die Festplattennutzung zu überprüfen.

Fazit

Beginnen Sie mit /var/log/nginx/error.log und überprüfen Sie dann, ob der vorgelagerte Dienst läuft und vom Nginx-Host aus erreichbar ist. Sobald Sie wissen, ob der Fehler auf Verbindungsverweigerung, Timeout, Berechtigungsverweigerung oder vorzeitiges Schließen zurückzuführen ist, liegt die Behebung in der Regel beim vorgelagerten Dienst, den Socket-Berechtigungen, den Timeout-Einstellungen oder der Firewall-Regel.