Comment diagnostiquer et résoudre les erreurs Nginx 502 Bad Gateway

Vous rencontrez une erreur Nginx 502 Bad Gateway ? Ce guide complet vous accompagne dans le diagnostic et la résolution du problème. Apprenez à interpréter les journaux d'erreurs Nginx, à vérifier l'état du serveur amont et à dépanner les causes courantes telles que les paramètres de proxy mal configurés, les problèmes de PHP-FPM, l'épuisement des ressources et les blocages de pare-feu. Grâce à des exemples pratiques et des solutions étape par étape, vous identifierez rapidement la cause première et restaurerez vos services web, assurant un fonctionnement fluide et un temps d'arrêt minimal.

50 vues

Comment diagnostiquer et résoudre les erreurs Nginx 502 Bad Gateway

Nginx est un serveur Web et un proxy inverse puissant et populaire, souvent utilisé pour servir du contenu statique, équilibrer la charge du trafic et transférer des requêtes vers divers serveurs d'applications en amont (upstream) tels que PHP-FPM, Node.js, Python Gunicorn ou Apache Tomcat. Lorsque Nginx rencontre un problème de communication avec l'un de ces serveurs en amont, il répond généralement par une erreur "502 Bad Gateway" (Mauvaise passerelle).

Cet article fournit un guide complet, étape par étape, pour comprendre, diagnostiquer et résoudre les erreurs Nginx 502 Bad Gateway. Nous explorerons les causes courantes, vous équiperons de techniques de dépannage pratiques à l'aide d'outils en ligne de commande et proposerons des solutions concrètes pour remettre vos services Web en ligne rapidement. Que vous soyez administrateur système, développeur ou que vous gériez votre propre serveur, ce guide vous aidera à gérer efficacement l'une des erreurs Nginx les plus courantes.

Comprendre l'erreur Nginx 502 Bad Gateway

Une erreur 502 Bad Gateway indique que Nginx, agissant comme un proxy inverse, a reçu une réponse invalide d'un serveur en amont. Cela signifie que Nginx s'est connecté avec succès à un serveur en amont, mais n'a reçu aucune réponse, une réponse incomplète ou une réponse qu'il n'a pas pu interpréter. Il est crucial de noter que le problème ne réside pas dans Nginx lui-même, mais dans le service avec lequel Nginx tente de communiquer.

Les serveurs en amont courants incluent :

  • PHP-FPM: Pour les applications PHP (par exemple, WordPress, Laravel).
  • Gunicorn/uWSGI: Pour les applications Python (par exemple, Django, Flask).
  • Node.js: Pour les applications JavaScript.
  • Apache Tomcat: Pour les applications Java.
  • Autres serveurs Web: Tels qu'Apache HTTP Server servant du contenu spécifique.

L'erreur 502 est un indicateur crucial que le backend de votre application ne fonctionne pas correctement ou est inaccessible à Nginx.

Diagnostic étape par étape

La clé pour résoudre une erreur 502 est un diagnostic systématique. Commencez par les coupables les plus probables et progressez dans votre investigation.

1. Vérifiez d'abord les journaux d'erreurs Nginx

Vos journaux d'erreurs Nginx sont la principale source d'information. Ils contiennent souvent des détails spécifiques sur la raison pour laquelle Nginx n'a pas pu communiquer avec le serveur en amont.

  • Emplacement: Généralement trouvé dans /var/log/nginx/error.log.
  • Commande: Utilisez tail -f pour surveiller les journaux en temps réel tout en essayant de reproduire l'erreur.
tail -f /var/log/nginx/error.log

Ce qu'il faut rechercher :
* connect() failed (111: Connection refused): Indique que le serveur en amont n'écoute pas sur l'adresse/le port spécifié ou qu'un pare-feu bloque la connexion.
* upstream timed out: Le serveur en amont a mis trop de temps à répondre.
* upstream prematurely closed connection: Le serveur en amont a fermé la connexion avant d'envoyer une réponse complète.
* no live upstreams while connecting to upstream: Nginx n'a trouvé aucun serveur en amont disponible configuré.

2. Vérifiez l'état du serveur en amont

Une fois que vous avez des indices dans les journaux d'erreurs Nginx, vérifiez l'état de votre serveur d'application en amont.

  • Pour PHP-FPM :

    bash systemctl status phpX.X-fpm # Remplacez X.X par votre version PHP, par exemple php7.4-fpm sudo service phpX.X-fpm status

  • Pour Node.js/Python/Autres applications personnalisées :
    Vérifiez si le processus est en cours d'exécution.

    bash ps aux | grep node ps aux | grep gunicorn
    Si vous utilisez un gestionnaire de processus comme PM2 (Node.js) ou Supervisor (général), vérifiez son état.

    bash pm2 status sudo supervisorctl status

Si le service n'est pas en cours d'exécution, essayez de le démarrer et vérifiez ses propres journaux pour détecter les erreurs.

systemctl start phpX.X-fpm
# Ou
sudo service phpX.X-fpm start

3. Vérifiez la connectivité réseau vers l'amont

Assurez-vous que Nginx peut atteindre le serveur en amont sur le port ou le chemin du socket configuré.

  • Pour les connexions TCP/IP (par exemple, 127.0.0.1:8000) :
    Utilisez telnet ou nc (netcat) pour tester la connectivité du port depuis le serveur Nginx.

    bash telnet 127.0.0.1 8000 nc -vz 127.0.0.1 8000
    Une connexion réussie devrait afficher Connected to 127.0.0.1. ou succeeded!. Si elle se bloque ou affiche Connection refused, le service en amont n'écoute pas ou un pare-feu la bloque.

  • Pour les sockets Unix (par exemple, unix:/run/php/phpX.X-fpm.sock) :
    Vérifiez que le fichier socket existe et possède les bonnes permissions.

    bash ls -l /run/php/phpX.X-fpm.sock
    Nginx doit avoir les permissions de lecture/écriture sur ce fichier socket. L'utilisateur Nginx (par exemple, www-data) doit faire partie du groupe propriétaire du socket (par exemple, www-data ou php-fpm).

Causes fréquentes et solutions

Sur la base de vos étapes de diagnostic, voici les causes les plus fréquentes des erreurs 502 et comment les résoudre.

1. Le serveur en amont n'est pas en cours d'exécution ou a planté

Cause : L'application vers laquelle Nginx tente de transférer (par exemple, PHP-FPM, Gunicorn, application Node.js) n'est pas en cours d'exécution ou a planté.

Solution : Démarrez ou redémarrez le service en amont.

# Exemple pour PHP-FPM
systemctl start phpX.X-fpm
# S'il est déjà en cours d'exécution et que vous soupçonnez un crash, redémarrez-le :
systemctl restart phpX.X-fpm

# Pour les applications personnalisées, utilisez leurs commandes start/restart spécifiques

Astuce : Assurez-vous que vos services en amont sont configurés pour démarrer automatiquement au démarrage du système. Pour les services systemd, utilisez systemctl enable phpX.X-fpm.

2. Surcharge du serveur en amont / Épuisement des ressources

Cause : Le serveur en amont est submergé, manque de mémoire, de CPU, ou atteint les limites de processus, ce qui l'empêche de répondre ou de refuser de nouvelles connexions.

Symptômes : Les journaux d'erreurs Nginx peuvent afficher connection refused ou upstream timed out par intermittence, surtout sous charge. Les outils de surveillance du système (top, htop, free -h) montrent une utilisation élevée des ressources.

Solutions :

  • Pour PHP-FPM : Ajustez les paramètres du pool PHP-FPM dans son fichier de configuration (par exemple, /etc/php/X.X/fpm/pool.d/www.conf).

    • pm.max_children : Le nombre maximum d'enfants pouvant être actifs en même temps.
    • pm.start_servers : Le nombre d'enfants créés au démarrage.
    • pm.min_spare_servers, pm.max_spare_servers : Contrôlent le nombre d'enfants inactifs conservés.

    ini ; Exemple pour la gestion dynamique des processus pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20
    * Augmentez memory_limit dans php.ini si les scripts épuisent la mémoire.
    * Pour les autres applications : Augmentez le nombre de processus de travail (worker processes), de threads, ou allouez plus de mémoire si possible. Surveillez les métriques spécifiques de votre application.
    * Délais d'attente (Timeouts) Nginx : Augmentez les directives proxy_connect_timeout, proxy_send_timeout et proxy_read_timeout de Nginx dans votre configuration Nginx, mais sachez que cela ne fait que retarder l'erreur si le backend est réellement en difficulté.

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

3. Configuration en amont incorrecte dans Nginx

Cause : Nginx est configuré pour se connecter à la mauvaise adresse IP, au mauvais port ou au mauvais chemin de socket Unix pour le serveur en amont.

Symptômes : Les journaux d'erreurs Nginx affichent connect() failed (111: Connection refused) immédiatement après une requête.

Solution : Examinez attentivement la configuration de votre bloc serveur Nginx (/etc/nginx/sites-available/your_site.conf).

  • Pour les upstreams HTTP/HTTPS :

    nginx location /app { proxy_pass http://127.0.0.1:8000; # Assurez-vous que l'IP et le port sont corrects proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }

  • Pour PHP-FPM via socket Unix :

    nginx location ~ \.php$ { fastcgi_pass unix:/run/php/phpX.X-fpm.sock; # Vérifiez que ce chemin correspond exactement à la configuration PHP-FPM fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

  • Pour PHP-FPM via TCP/IP :

    nginx location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; # Vérifiez l'IP et le port fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

Après avoir effectué des modifications, testez toujours votre configuration Nginx et rechargez/redémarrez Nginx :

nginx -t
systemctl reload nginx # Ou redémarrez si -t indique un besoin

4. Dépassement du délai d'attente request_terminate_timeout de PHP-FPM

Cause : Un script PHP prend plus de temps à s'exécuter que le paramètre request_terminate_timeout dans PHP-FPM. Nginx attend la réponse, mais PHP-FPM termine le script, ce qui amène Nginx à recevoir une réponse incomplète.

Symptômes : Les journaux d'erreurs Nginx peuvent afficher upstream timed out ou script timed out. Les journaux PHP-FPM peuvent afficher child XX exited on signal 9 (SIGKILL).

Solution :
* Augmentez request_terminate_timeout : Dans votre configuration de pool PHP-FPM (www.conf), trouvez et ajustez cette directive. La régler sur 0 désactive le délai d'attente, mais ce n'est généralement pas recommandé car les scripts longs peuvent monopoliser les ressources.

```ini
request_terminate_timeout = 300 # Augmentez à 5 minutes (300 secondes)
```
  • Augmentez fastcgi_read_timeout dans Nginx : Ce délai d'attente Nginx doit être égal ou supérieur à request_terminate_timeout.

    nginx location ~ \.php$ { ... fastcgi_read_timeout 300s; # Doit être >= request_terminate_timeout de PHP-FPM ... }

Attention : Bien qu'augmenter les délais d'attente puisse résoudre l'erreur 502, cela peut masquer des problèmes de performance sous-jacents. La meilleure solution à long terme est d'optimiser le script PHP lent.

5. Problèmes de pare-feu

Cause : Un pare-feu (soit sur le serveur Nginx, soit sur le serveur en amont s'ils sont séparés) bloque les connexions vers le port ou le socket en amont.

Solution :
* Vérifiez l'état du pare-feu :

```bash
sudo ufw status # Pour UFW (Ubuntu/Debian)
sudo firewall-cmd --list-all # Pour firewalld (CentOS/RHEL)
sudo iptables -L # Pour iptables
```
  • Ouvrez les ports nécessaires : Assurez-vous que le port que Nginx utilise pour se connecter à l'amont (par exemple, 9000 pour PHP-FPM via TCP/IP) est ouvert.

    bash sudo ufw allow from 127.0.0.1 to any port 9000 # Autoriser localhost à se connecter à 9000 sudo firewall-cmd --permanent --add-port=9000/tcp # Pour firewalld sudo firewall-cmd --reload
    * Désactivez temporairement le pare-feu à des fins de test uniquement dans un environnement contrôlé, puis réactivez-le et configurez-le correctement.

6. Interférence SELinux ou AppArmor

Cause : Les améliorations de sécurité comme SELinux (sur RHEL/CentOS) ou AppArmor (sur Ubuntu/Debian) peuvent empêcher Nginx d'accéder au socket en amont ou d'établir des connexions réseau, même si les permissions de fichiers et les pare-feu sont correctement configurés.

Symptômes : Les journaux peuvent afficher des messages de type permission denied (permission refusée) ou similaires, en particulier dans /var/log/audit/audit.log (pour SELinux).

Solution :
* Vérifiez audit.log :

```bash
sudo grep nginx /var/log/audit/audit.log
```
  • Définissez temporairement SELinux en mode permissif : sudo setenforce 0. Si l'erreur disparaît, SELinux est le coupable. Vous devrez alors générer et appliquer les politiques SELinux appropriées (par exemple, audit2allow). N'oubliez pas de le remettre en mode d'application (sudo setenforce 1).
  • Vérifiez l'état d'AppArmor : sudo aa-status. Si AppArmor est actif, vous devrez peut-être ajuster le profil Nginx.

7. Corps de requête/réponse volumineux (Mise en cache proxy)

Cause : Les paramètres de mise en cache proxy par défaut de Nginx sont peut-être trop petits pour les corps de requête ou de réponse très volumineux, ce qui entraîne une fermeture prématurée de la connexion.

Symptômes : Les journaux d'erreurs Nginx peuvent afficher upstream prematurely closed connection while reading response header from upstream ou upstream prematurely closed connection while reading response body from upstream.

Solution : Ajustez les directives de mise en cache proxy Nginx dans votre bloc http, server ou location.

http {
    ...
    proxy_buffer_size   128k; # Taille du tampon pour la première partie de la réponse
    proxy_buffers   4 256k; # Nombre et taille des tampons pour le reste de la réponse
    proxy_busy_buffers_size   256k; # Taille maximale des tampons occupés
    proxy_temp_file_write_size 256k; # Taille pour l'écriture dans les fichiers temporaires si la mise en cache déborde
    ...
}

Remarque : Ces paramètres consomment plus de mémoire. Ajustez-les avec prudence en fonction des ressources de votre serveur et de la taille typique des réponses de votre application.

Conseils généraux de dépannage

  • Examinez tous les journaux pertinents : En plus des journaux d'erreurs Nginx, vérifiez également les journaux d'accès Nginx, les journaux de l'application en amont (PHP-FPM, Gunicorn, journaux de l'application Node.js) et les journaux système (/var/log/syslog, dmesg).
  • Redémarrez Nginx : Après toute modification de configuration, redémarrez toujours Nginx pour vous assurer qu'elle prend effet : systemctl restart nginx.
  • Testez la configuration Nginx : Avant de redémarrer, validez la syntaxe de votre configuration Nginx : nginx -t.
  • Isolez le problème : Essayez de contourner Nginx et d'accéder directement à l'application en amont. Par exemple, si votre application Node.js est sur localhost:3000, utilisez curl http://localhost:3000 depuis la ligne de commande du serveur. Si cela échoue également, le problème vient certainement de votre application, pas de Nginx.
  • Vérifiez l'espace disque : Un disque plein peut empêcher les applications d'écrire des fichiers temporaires ou des journaux, entraînant des plantages ou des échecs. Utilisez df -h pour vérifier l'utilisation du disque.

Conclusion

Les erreurs Nginx 502 Bad Gateway sont courantes mais indiquent presque toujours un problème avec l'application backend que Nginx essaie de contacter, et non avec Nginx lui-même. En vérifiant systématiquement vos journaux d'erreurs Nginx, en vérifiant l'état du serveur en amont, en confirmant la connectivité réseau, puis en abordant les problèmes courants de configuration ou de ressources, vous pouvez diagnostiquer et résoudre efficacement ces problèmes.

N'oubliez pas d'aborder le dépannage de manière méthodique, en commençant par les vérifications les plus basiques et en approfondissant progressivement. Testez toujours votre configuration Nginx après avoir effectué des modifications et surveillez la santé de votre application et de votre serveur pour éviter les problèmes futurs. Grâce à ces stratégies, vous serez bien équipé pour maintenir vos services en bon état de fonctionnement.