Cómo Diagnosticar y Resolver Errores 502 Bad Gateway de Nginx
Soluciona errores 502 de Nginx revisando registros de errores, estado del upstream, permisos de sockets, configuración del proxy, tiempos de espera y cortafuegos.
Cómo Diagnosticar y Resolver Errores 502 Bad Gateway de Nginx
Nginx es un servidor web y proxy inverso potente y popular, a menudo utilizado para servir contenido estático, equilibrar el tráfico y reenviar solicitudes a varios servidores de aplicaciones upstream como PHP-FPM, Node.js, Python Gunicorn o Apache Tomcat. Cuando Nginx encuentra un problema al comunicarse con uno de estos servidores upstream, normalmente responde con un error "502 Bad Gateway".
Comience con el registro de errores de Nginx, luego verifique si el proceso upstream está en ejecución, es accesible y puede responder.
Comprendiendo el Error 502 Bad Gateway de Nginx
Un error 502 Bad Gateway indica que Nginx, actuando como proxy inverso, recibió una respuesta no válida de un servidor upstream. Significa que Nginx se conectó exitosamente a un servidor upstream pero recibió ninguna respuesta, una respuesta incompleta o una respuesta que no pudo entender. Es crucial entender que el problema no está en Nginx en sí, sino en el servicio con el que Nginx intenta comunicarse.
Los servidores upstream comunes incluyen:
- PHP-FPM: Para aplicaciones PHP (ej., WordPress, Laravel).
- Gunicorn/uWSGI: Para aplicaciones Python (ej., Django, Flask).
- Node.js: Para aplicaciones JavaScript.
- Apache Tomcat: Para aplicaciones Java.
- Otros servidores web: Como Apache HTTP Server sirviendo contenido específico.
El error 502 es un indicador crucial de que el backend de su aplicación no funciona correctamente o es inaccesible para Nginx.
Diagnóstico Paso a Paso
La clave para resolver un error 502 es un diagnóstico sistemático. Comience con los culpables más probables e investigue progresivamente más a fondo.
1. Revise los Registros de Errores de Nginx Primero
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 upstream.
- Ubicación: Típicamente en
/var/log/nginx/error.log. - Comando: Use
tail -fpara 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 upstream no está escuchando en la dirección/puerto especificado o que un cortafuegos está bloqueando la conexión.upstream timed out: El servidor upstream tardó demasiado en responder.upstream prematurely closed connection: El servidor upstream cerró la conexión antes de enviar una respuesta completa.no live upstreams while connecting to upstream: Nginx no pudo encontrar ningún servidor upstream disponible configurado.
2. Verifique el Estado del Servidor Upstream
Una vez que tenga pistas de los registros de errores de Nginx, verifique el estado de su servidor de aplicaciones upstream.
Para PHP-FPM:
sudo systemctl status php8.2-fpmPara Node.js/Python/Otras Aplicaciones Personalizadas: Verifique si el proceso está en ejecución.
ps aux | grep node ps aux | grep gunicornSi usa un administrador de procesos como PM2 (Node.js) o Supervisor (general), verifique su estado.
pm2 status sudo supervisorctl status
Si el servicio no se está ejecutando, intente iniciarlo y revise sus propios registros en busca de errores.
sudo systemctl start php8.2-fpm
3. Verifique la Conectividad de Red al Upstream
Asegúrese de que Nginx pueda alcanzar el servidor upstream en el puerto o ruta de socket configurado.
Para conexiones TCP/IP (ej.,
127.0.0.1:8000): Usetelnetonc(netcat) para probar la conectividad del puerto desde el servidor Nginx.telnet 127.0.0.1 8000 nc -vz 127.0.0.1 8000Una conexión exitosa debería mostrar
Connected to 127.0.0.1.osucceeded!. Si se cuelga o muestraConnection refused, el servicio upstream no está escuchando o un cortafuegos lo está bloqueando.Para sockets Unix (ej.,
unix:/run/php/phpX.X-fpm.sock): Verifique que el archivo de socket exista y tenga los permisos correctos.ls -l /run/php/phpX.X-fpm.sockNginx debe tener permisos de lectura/escritura en este archivo de socket. El usuario de Nginx (ej.,
www-data) debe ser parte del grupo que posee el socket (ej.,www-dataophp-fpm).
Causas Comunes y Soluciones
Basado en sus pasos de diagnóstico, aquí están las causas más frecuentes de errores 502 y cómo resolverlas.
1. Servidor Upstream No en Ejecución o Bloqueado
Causa: La aplicación a la que Nginx intenta hacer proxy (ej., PHP-FPM, Gunicorn, aplicación Node.js) no se está ejecutando o se ha bloqueado.
Solución: Inicie o reinicie el servicio upstream.
# Ejemplo para PHP-FPM
sudo systemctl start php8.2-fpm
# Si ya está en ejecución y sospecha un bloqueo, reinícielo:
sudo systemctl restart php8.2-fpm
# Para aplicaciones personalizadas, use sus comandos específicos de inicio/reinicio
Consejo: Asegúrese de que sus servicios upstream estén configurados para iniciarse automáticamente al arrancar el sistema. Para servicios systemd, use systemctl enable phpX.X-fpm.
2. Sobrecarga del Servidor Upstream / Agotamiento de Recursos
Causa: El servidor upstream está abrumado, quedándose sin memoria, CPU o alcanzando límites de procesos, lo que provoca que deje de responder o rechace nuevas conexiones.
Síntomas: Los registros de errores de Nginx pueden 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 (ej.,
/etc/php/X.X/fpm/pool.d/www.conf).pm.max_children: El número máximo de hijos que pueden estar vivos al mismo tiempo.pm.start_servers: El número de hijos creados al inicio.pm.min_spare_servers,pm.max_spare_servers: Controla cuántos hijos inactivos se mantienen.
; 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_limitenphp.inisi los scripts agotan 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 de Nginx: Aumente las directivas
proxy_connect_timeout,proxy_send_timeoutyproxy_read_timeouten su configuración de Nginx, pero entienda que esto solo retrasa el error si el backend realmente tiene problemas.http { ... proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; ... }
3. Configuración Incorrecta del Upstream en Nginx
Causa: Nginx está configurado para conectarse a la dirección IP, puerto o ruta de socket Unix incorrecta para el servidor upstream.
Síntomas: Los registros de errores de Nginx muestran connect() failed (111: Connection refused) inmediatamente después de una solicitud.
Solución: Revise cuidadosamente la configuración del bloque de servidor de Nginx (/etc/nginx/sites-available/your_site.conf).
Para upstreams HTTP/HTTPS:
location /app { proxy_pass http://127.0.0.1:8000; # Asegúrese de que IP y 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 a través de socket Unix:
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 a través de TCP/IP:
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 hacer cambios, siempre pruebe su configuración de Nginx y recargue/reinicie Nginx:
nginx -t
systemctl reload nginx # O reinicie si -t indica que es necesario
4. Se Superó el request_terminate_timeout de PHP-FPM
Causa: Un script PHP tarda más en ejecutarse que la configuración request_terminate_timeout en PHP-FPM. Nginx espera la respuesta, pero PHP-FPM termina el script, lo que provoca que Nginx reciba una respuesta incompleta.
Síntomas: Los registros de errores de Nginx pueden mostrar upstream timed out o script timed out. Los registros de PHP-FPM pueden mostrar child XX exited on signal 9 (SIGKILL).
Solución:
Aumente
request_terminate_timeout: En la configuración del pool de PHP-FPM (www.conf), busque y ajuste esta directiva. Configurarlo en0deshabilita el tiempo de espera, pero generalmente no se recomienda ya que los scripts de larga duración pueden colgar recursos.request_terminate_timeout = 300 # Aumente a 5 minutos (300 segundos)Aumente
fastcgi_read_timeouten Nginx: Este tiempo de espera de Nginx debe ser igual o mayor querequest_terminate_timeout.location ~ \.php$ { ... fastcgi_read_timeout 300s; # Debe ser >= request_terminate_timeout de PHP-FPM ... }
Advertencia: Aunque aumentar los tiempos de espera puede resolver el error 502, podría ocultar problemas de rendimiento subyacentes. La mejor solución a largo plazo es optimizar el script PHP lento.
5. Problemas de Cortafuegos
Causa: Un cortafuegos (ya sea en el servidor Nginx o en el servidor upstream si están separados) está bloqueando las conexiones al puerto o socket upstream.
Solución:
Verifique el estado del cortafuegos:
sudo ufw status # Para UFW (Ubuntu/Debian) sudo firewall-cmd --list-all # Para firewalld (CentOS/RHEL) sudo iptables -L # Para iptablesAbra los puertos necesarios: Asegúrese de que el puerto que Nginx usa para conectarse al upstream (ej., 9000 para PHP-FPM a través de TCP/IP) esté abierto.
sudo ufw allow from 127.0.0.1 to any port 9000 # Permitir localhost para conectarse al 9000 sudo firewall-cmd --permanent --add-port=9000/tcp # Para firewalld sudo firewall-cmd --reloadDesactive temporalmente el cortafuegos para pruebas solo en un entorno controlado, luego vuelva a activarlo y configúrelo correctamente.
6. Interferencia de SELinux o AppArmor
Causa: Las mejoras de seguridad como SELinux (en RHEL/CentOS) o AppArmor (en Ubuntu/Debian) podrían estar impidiendo que Nginx acceda al socket upstream o realice conexiones de red, incluso si los permisos de archivos y los cortafuegos están configurados correctamente.
Síntomas: Los registros pueden mostrar permission denied o mensajes similares, especialmente en /var/log/audit/audit.log (para SELinux).
Solución:
Verifique
audit.log:sudo grep nginx /var/log/audit/audit.logEstablezca temporalmente SELinux en modo permisivo:
sudo setenforce 0. Si el error se resuelve, SELinux es el culpable. Luego deberá generar y aplicar políticas SELinux apropiadas (ej.,audit2allow). Recuerde volver a configurarlo en modo enforcing (sudo setenforce 1).Verifique el estado de AppArmor:
sudo aa-status. Si AppArmor está activo, es posible que deba ajustar el perfil de Nginx.
7. Cuerpos de Solicitud/Respuesta Grandes (Proxy Buffering)
Causa: La configuración predeterminada de proxy buffering de Nginx podría ser demasiado pequeña para cuerpos de solicitud o respuesta muy grandes, lo que lleva a un cierre prematuro de la conexión.
Síntomas: Los registros de errores de Nginx pueden 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 proxy buffering de Nginx en su bloque http, server o location.
http {
...
proxy_buffer_size 128k; # Tamaño del búfer para la primera parte de la respuesta
proxy_buffers 4 256k; # Número y tamaño de los búferes para el resto de la respuesta
proxy_busy_buffers_size 256k; # Tamaño máximo de los búferes 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 cuidado 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, también revise los registros de acceso de Nginx, los registros de la aplicación upstream (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 y acceder directamente a la aplicación upstream. Por ejemplo, si su aplicación Node.js está en
localhost:3000, usecurl http://localhost:3000desde la línea de comandos del servidor. Si esto también falla, el problema está definitivamente en su aplicación, no en Nginx. - Verifique el Espacio en Disco: Un disco lleno puede impedir que las aplicaciones escriban archivos temporales o registros, lo que provoca bloqueos o fallos. Use
df -hpara verificar el uso del disco.
Conclusión
Comience con /var/log/nginx/error.log, luego verifique que el upstream esté en ejecución y sea accesible desde el host de Nginx. Una vez que sepa si la falla es conexión rechazada, tiempo de espera, permiso denegado o cierre prematuro, la solución generalmente está en el servicio upstream, los permisos del socket, la configuración de tiempos de espera o la regla del cortafuegos.