Cómo diagnosticar y resolver errores de Nginx 502 Bad Gateway

¿Te encuentras con un error Nginx 502 Bad Gateway? Esta guía completa te acompaña en el diagnóstico y la resolución del problema. Aprende a interpretar los registros de errores de Nginx, a verificar el estado del servidor upstream y a solucionar problemas comunes como configuraciones de proxy incorrectas, problemas de PHP-FPM, agotamiento de recursos y bloqueos de firewall. Con ejemplos prácticos y soluciones paso a paso, identificarás rápidamente la causa raíz y restaurarás tus servicios web, garantizando un funcionamiento sin problemas y un tiempo de inactividad mínimo.

51 vistas

Cómo diagnosticar y resolver errores 502 Bad Gateway de Nginx

Nginx es un servidor web y proxy inverso potente y popular, utilizado a menudo para servir contenido estático, balancear la carga del tráfico y reenviar peticiones a varios servidores de aplicaciones ascendentes (upstream) como PHP-FPM, Node.js, Python Gunicorn o Apache Tomcat. Cuando Nginx encuentra un problema al comunicarse con uno de estos servidores ascendentes, normalmente responde con un error "502 Bad Gateway".

Este artículo proporciona una guía completa paso a paso para comprender, diagnosticar y resolver los errores 502 Bad Gateway de Nginx. Exploraremos las causas comunes, le equiparemos con técnicas prácticas de solución de problemas utilizando herramientas de línea de comandos y ofreceremos soluciones prácticas para que sus servicios web vuelvan a estar en línea rápidamente. Ya sea usted un administrador de sistemas, un desarrollador o esté administrando su propio servidor, esta guía le ayudará a abordar eficazmente uno de los errores más comunes de Nginx.

Entendiendo el Error 502 Bad Gateway de Nginx

Un error 502 Bad Gateway indica que Nginx, actuando como proxy inverso, recibió una respuesta inválida de un servidor ascendente. Significa que Nginx se conectó con éxito a un servidor ascendente pero recibió ninguna respuesta, una respuesta incompleta o una respuesta que no pudo entender. Fundamentalmente, el problema no reside en Nginx en sí, sino en el servicio con el que Nginx intenta comunicarse.

Los servidores ascendentes comunes incluyen:

  • PHP-FPM: Para aplicaciones PHP (p. ej., WordPress, Laravel).
  • Gunicorn/uWSGI: Para aplicaciones Python (p. ej., Django, Flask).
  • Node.js: Para aplicaciones JavaScript.
  • Apache Tomcat: Para aplicaciones Java.
  • Otros servidores web: Como Apache HTTP Server sirviendo contenido específico.

The 502 error is a crucial indicator that your application's backend is not functioning correctly or is inaccessible to Nginx.

Diagnóstico Paso a Paso

La clave para resolver un error 502 es el diagnóstico sistemático. Comience con los culpables más probables e investigue progresivamente más a fondo.

1. Revise Primero los Registros de Errores de Nginx

Sus registros de errores de Nginx son la fuente principal de información. A menudo contienen detalles específicos sobre por qué Nginx no pudo comunicarse con el servidor ascendente.

  • Ubicación: Típicamente se encuentran en /var/log/nginx/error.log.
  • Comando: Use tail -f para monitorear los registros en tiempo real mientras intenta reproducir el error.
tail -f /var/log/nginx/error.log

Qué buscar:
* connect() failed (111: Connection refused): Indica que el servidor ascendente no está escuchando en la dirección/puerto especificado o que un cortafuegos está bloqueando la conexión.
* upstream timed out: El servidor ascendente tardó demasiado en responder.
* upstream prematurely closed connection: El servidor ascendente cerró la conexión antes de enviar una respuesta completa.
* no live upstreams while connecting to upstream: Nginx no pudo encontrar servidores ascendentes disponibles configurados.

2. Verifique el Estado del Servidor Ascendente

Una vez que tenga pistas de los registros de errores de Nginx, compruebe el estado de su servidor de aplicaciones ascendente.

  • Para PHP-FPM:

    bash systemctl status phpX.X-fpm # Reemplace X.X con su versión de PHP, p. ej., php7.4-fpm sudo service phpX.X-fpm status

  • Para Node.js/Python/Otras Aplicaciones Personalizadas:
    Verifique si el proceso se está ejecutando.

    bash ps aux | grep node ps aux | grep gunicorn
    Si utiliza un gestor de procesos como PM2 (Node.js) o Supervisor (general), compruebe su estado.

    bash pm2 status sudo supervisorctl status

Si el servicio no se está ejecutando, intente iniciarlo y revise sus propios registros en busca de errores.

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

3. Compruebe la Conectividad de Red con el Ascendente

Asegúrese de que Nginx puede alcanzar el servidor ascendente en el puerto o la ruta del socket configurados.

  • Para conexiones TCP/IP (p. ej., 127.0.0.1:8000):
    Use telnet o nc (netcat) para probar la conectividad del puerto desde el servidor Nginx.

    bash telnet 127.0.0.1 8000 nc -vz 127.0.0.1 8000
    Una conexión exitosa debería mostrar Connected to 127.0.0.1. o succeeded!. Si se cuelga o muestra Connection refused, el servicio ascendente no está escuchando o un cortafuegos lo está bloqueando.

  • Para sockets Unix (p. ej., unix:/run/php/phpX.X-fpm.sock):
    Verifique que el archivo de socket exista y tenga los permisos correctos.

    bash ls -l /run/php/phpX.X-fpm.sock
    Nginx debe tener permisos de lectura/escritura para este archivo de socket. El usuario de Nginx (p. ej., www-data) debe pertenecer al grupo propietario del socket (p. ej., www-data o php-fpm).

Causas Comunes y Soluciones

Basándose en sus pasos de diagnóstico, estas son las causas más frecuentes de los errores 502 y cómo resolverlas.

1. El Servidor Ascendente No se Está Ejecutando o Ha Fallado

Causa: La aplicación a la que Nginx intenta reenviar (p. ej., PHP-FPM, Gunicorn, aplicación Node.js) no se está ejecutando o ha fallado.

Solución: Inicie o reinicie el servicio ascendente.

# Ejemplo para PHP-FPM
systemctl start phpX.X-fpm
# Si ya se está ejecutando y sospecha de un fallo, reinícielo:
systemctl restart phpX.X-fpm

# Para aplicaciones personalizadas, utilice sus comandos específicos de inicio/reinicio

Consejo: Asegúrese de que sus servicios ascendentes estén configurados para iniciarse automáticamente al arrancar el sistema. Para servicios systemd, use systemctl enable phpX.X-fpm.

2. Sobrecarga del Servidor Ascendente / Agotamiento de Recursos

Causa: El servidor ascendente está abrumado, quedándose sin memoria, CPU o alcanzando los límites de procesos, lo que provoca que deje de responder o rechace nuevas conexiones.

Síntomas: Los registros de errores de Nginx podrían mostrar connection refused o upstream timed out de forma intermitente, especialmente bajo carga. Las herramientas de monitoreo del sistema (top, htop, free -h) muestran un alto uso de recursos.

Soluciones:

  • Para PHP-FPM: Ajuste la configuración del pool de PHP-FPM en su archivo de configuración (p. ej., /etc/php/X.X/fpm/pool.d/www.conf).

    • pm.max_children: El número máximo de procesos hijos que pueden estar activos al mismo tiempo.
    • pm.start_servers: El número de procesos hijos creados al inicio.
    • pm.min_spare_servers, pm.max_spare_servers: Controlan cuántos procesos hijos inactivos se mantienen.

    ini ; Ejemplo para gestión dinámica de procesos pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20
    * Aumente memory_limit en php.ini si los scripts están agotando la memoria.
    * Para otras aplicaciones: Aumente el número de procesos de trabajo, hilos o asigne más memoria si es posible. Monitoree las métricas específicas de su aplicación.
    * Tiempos de espera (Timeouts) de Nginx: Aumente las directivas proxy_connect_timeout, proxy_send_timeout y proxy_read_timeout de Nginx en su configuración de Nginx, pero entienda que esto solo retrasará el error si el backend realmente está luchando.

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

3. Configuración Ascendente Incorrecta en Nginx

Causa: Nginx está configurado para conectarse a la IP, el puerto o la ruta del socket Unix incorrectos para el servidor ascendente.

Síntomas: Los registros de errores de Nginx muestran connect() failed (111: Connection refused) inmediatamente después de una petición.

Solución: Revise cuidadosamente la configuración del bloque de servidor de Nginx (/etc/nginx/sites-available/your_site.conf).

  • Para upstreams HTTP/HTTPS:

    nginx location /app { proxy_pass http://127.0.0.1:8000; # Asegúrese de que la IP y el puerto sean correctos proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }

  • Para PHP-FPM vía socket Unix:

    nginx location ~ \.php$ { fastcgi_pass unix:/run/php/phpX.X-fpm.sock; # Verifique que esta ruta coincida exactamente con la configuración de PHP-FPM fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

  • Para PHP-FPM vía TCP/IP:

    nginx location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; # Verifique IP y puerto fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

Después de realizar cambios, siempre pruebe su configuración de Nginx y recargue/reinicie Nginx:

nginx -t
systemctl reload nginx # O reinicie si -t indica la necesidad

4. Se Superó el request_terminate_timeout de PHP-FPM

Causa: Un script PHP tarda más en ejecutarse que el valor de request_terminate_timeout configurado en PHP-FPM. Nginx espera la respuesta, pero PHP-FPM termina el script, haciendo que Nginx reciba una respuesta incompleta.

Síntomas: Los registros de errores de Nginx podrían mostrar upstream timed out o script timed out. Los registros de PHP-FPM podrían mostrar child XX exited on signal 9 (SIGKILL).

Solución:
* Aumente request_terminate_timeout: En la configuración de su pool de PHP-FPM (www.conf), encuentre y ajuste esta directiva. Configurarla en 0 deshabilita el tiempo de espera, pero generalmente no se recomienda, ya que los scripts de larga ejecución pueden acaparar recursos.

```ini
request_terminate_timeout = 300 # Aumentar a 5 minutos (300 segundos)
```
  • Aumente fastcgi_read_timeout en Nginx: Este tiempo de espera de Nginx debe ser igual o mayor que request_terminate_timeout.

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

Advertencia: Si bien aumentar los tiempos de espera puede resolver el error 502, puede ocultar problemas de rendimiento subyacentes. La mejor solución a largo plazo es optimizar el script PHP lento.

5. Problemas de Cortafuegos (Firewall)

Causa: Un cortafuegos (ya sea en el servidor Nginx o en el servidor ascendente si son diferentes) está bloqueando las conexiones al puerto o socket ascendente.

Solución:
* Compruebe el estado del cortafuegos:

```bash
sudo ufw status # Para UFW (Ubuntu/Debian)
sudo firewall-cmd --list-all # Para firewalld (CentOS/RHEL)
sudo iptables -L # Para iptables
```
  • Abra los puertos necesarios: Asegúrese de que el puerto que Nginx utiliza para conectarse al ascendente (p. ej., 9000 para PHP-FPM vía TCP/IP) esté abierto.

    bash sudo ufw allow from 127.0.0.1 to any port 9000 # Permitir que localhost se conecte al 9000 sudo firewall-cmd --permanent --add-port=9000/tcp # Para firewalld sudo firewall-cmd --reload
    * Deshabilite temporalmente el cortafuegos con fines de prueba solo en un entorno controlado, y luego vuelva a habilitarlo y configúrelo correctamente.

6. Interferencia de SELinux o AppArmor

Causa: Mejoras de seguridad como SELinux (en RHEL/CentOS) o AppArmor (en Ubuntu/Debian) podrían estar impidiendo que Nginx acceda al socket ascendente o realice conexiones de red, incluso si los permisos de archivo y los cortafuegos están configurados correctamente.

Síntomas: Los registros podrían mostrar mensajes como permission denied o similares, especialmente en /var/log/audit/audit.log (para SELinux).

Solución:
* Revise audit.log:

```bash
sudo grep nginx /var/log/audit/audit.log
```
  • Establezca temporalmente SELinux en modo permisivo: sudo setenforce 0. Si el error se resuelve, SELinux es el culpable. Luego deberá generar y aplicar las políticas SELinux apropiadas (p. ej., audit2allow). Recuerde volver a ponerlo en modo de aplicación (sudo setenforce 1).
  • Compruebe el estado de AppArmor: sudo aa-status. Si AppArmor está activo, es posible que deba ajustar el perfil de Nginx.

7. Cuerpos de Petición/Respuesta Grandes (Buffering de Proxy)

Causa: La configuración predeterminada de buffering de proxy de Nginx podría ser demasiado pequeña para cuerpos de petición o respuesta muy grandes, lo que provoca un cierre prematuro de la conexión.

Síntomas: Los registros de errores de Nginx podrían mostrar upstream prematurely closed connection while reading response header from upstream o upstream prematurely closed connection while reading response body from upstream.

Solución: Ajuste las directivas de buffering de proxy de Nginx en su bloque http, server o location.

http {
    ...
    proxy_buffer_size   128k; # Tamaño del buffer para la primera parte de la respuesta
    proxy_buffers   4 256k; # Número y tamaño de los buffers para el resto de la respuesta
    proxy_busy_buffers_size   256k; # Tamaño máximo de los buffers ocupados
    proxy_temp_file_write_size 256k; # Tamaño para escribir en archivos temporales si el buffering se desborda
    ...
}

Nota: Estas configuraciones consumen más memoria. Ajústelas con cautela según los recursos de su servidor y el tamaño típico de las respuestas de su aplicación.

Consejos Generales de Solución de Problemas

  • Revise todos los registros relevantes: Además de los registros de errores de Nginx, revise también los registros de acceso de Nginx, los registros de la aplicación ascendente (PHP-FPM, Gunicorn, registros de la aplicación Node.js) y los registros del sistema (/var/log/syslog, dmesg).
  • Reinicie Nginx: Después de cualquier cambio de configuración, reinicie siempre Nginx para asegurarse de que surtan efecto: systemctl restart nginx.
  • Pruebe la configuración de Nginx: Antes de reiniciar, valide la sintaxis de su configuración de Nginx: nginx -t.
  • Aísle el problema: Intente omitir Nginx e acceder a la aplicación ascendente directamente. Por ejemplo, si su aplicación Node.js está en localhost:3000, use curl http://localhost:3000 desde la línea de comandos del servidor. Si esto también falla, el problema está definitivamente con su aplicación, no con Nginx.
  • Compruebe el espacio en disco: Un disco lleno puede impedir que las aplicaciones escriban archivos temporales o registros, lo que provoca fallos o errores. Use df -h para verificar el uso del disco.

Conclusión

Los errores 502 Bad Gateway de Nginx son comunes, pero casi siempre apuntan a un problema con la aplicación de backend a la que Nginx intenta conectarse, no a Nginx en sí. Al verificar sistemáticamente los registros de errores de Nginx, verificar el estado del servidor ascendente, confirmar la conectividad de red y luego abordar los problemas comunes de configuración o recursos, puede diagnosticar y resolver eficazmente estos problemas.

Recuerde abordar la solución de problemas metódicamente, comenzando con las comprobaciones más básicas y profundizando progresivamente. Siempre pruebe su configuración de Nginx después de realizar cambios y monitoree la salud de su aplicación y servidor para prevenir futuras ocurrencias. Con estas estrategias, estará bien equipado para mantener sus servicios funcionando sin problemas.