Como Diagnosticar e Resolver Erros 502 Bad Gateway no Nginx

Corrija erros 502 do Nginx verificando logs de erro, saúde do upstream, permissões de socket, configurações de proxy, timeouts e firewalls.

Como Diagnosticar e Resolver Erros 502 Bad Gateway no Nginx

O Nginx é um servidor web e proxy reverso poderoso e popular, frequentemente usado para servir conteúdo estático, balancear tráfego e encaminhar requisições para vários servidores de aplicação upstream, como PHP-FPM, Node.js, Python Gunicorn ou Apache Tomcat. Quando o Nginx encontra um problema ao se comunicar com um desses servidores upstream, ele normalmente responde com um erro "502 Bad Gateway".

Comece pelo log de erros do Nginx, depois verifique se o processo upstream está em execução, acessível e autorizado a responder.

Entendendo o Erro 502 Bad Gateway do Nginx

Um erro 502 Bad Gateway indica que o Nginx, atuando como proxy reverso, recebeu uma resposta inválida de um servidor upstream. Isso significa que o Nginx se conectou com sucesso a um servidor upstream, mas não recebeu resposta, recebeu uma resposta incompleta ou uma resposta que não conseguiu entender. Crucialmente, o problema não está no Nginx em si, mas no serviço com o qual o Nginx está tentando se comunicar.

Servidores upstream comuns incluem:

  • PHP-FPM: Para aplicações PHP (ex.: WordPress, Laravel).
  • Gunicorn/uWSGI: Para aplicações Python (ex.: Django, Flask).
  • Node.js: Para aplicações JavaScript.
  • Apache Tomcat: Para aplicações Java.
  • Outros servidores web: Como o Apache HTTP Server servindo conteúdo específico.

O erro 502 é um indicador crucial de que o backend da sua aplicação não está funcionando corretamente ou está inacessível para o Nginx.

Diagnóstico Passo a Passo

A chave para resolver um erro 502 é o diagnóstico sistemático. Comece pelos culpados mais prováveis e investigue progressivamente.

1. Verifique os Logs de Erro do Nginx Primeiro

Seus logs de erro do Nginx são a principal fonte de informação. Eles frequentemente contêm detalhes específicos sobre por que o Nginx não conseguiu se comunicar com o servidor upstream.

  • Localização: Normalmente encontrado em /var/log/nginx/error.log.
  • Comando: Use tail -f para monitorar os logs em tempo real enquanto tenta reproduzir o erro.
tail -f /var/log/nginx/error.log

O que procurar:

  • connect() failed (111: Connection refused): Indica que o servidor upstream não está ouvindo no endereço/porta especificados ou um firewall está bloqueando a conexão.
  • upstream timed out: O servidor upstream demorou muito para responder.
  • upstream prematurely closed connection: O servidor upstream fechou a conexão antes de enviar uma resposta completa.
  • no live upstreams while connecting to upstream: O Nginx não conseguiu encontrar nenhum servidor upstream disponível configurado.

2. Verifique o Status do Servidor Upstream

Assim que tiver pistas dos logs de erro do Nginx, verifique o status do seu servidor de aplicação upstream.

  • Para PHP-FPM:

    sudo systemctl status php8.2-fpm
    
  • Para Node.js/Python/Outras Aplicações Customizadas: Verifique se o processo está em execução.

    ps aux | grep node
    ps aux | grep gunicorn
    

    Se estiver usando um gerenciador de processos como PM2 (Node.js) ou Supervisor (geral), verifique seu status.

    pm2 status
    sudo supervisorctl status
    

Se o serviço não estiver em execução, tente iniciá-lo e verifique seus próprios logs em busca de erros.

sudo systemctl start php8.2-fpm

3. Verifique a Conectividade de Rede com o Upstream

Certifique-se de que o Nginx pode alcançar o servidor upstream na porta ou caminho de socket configurado.

  • Para conexões TCP/IP (ex.: 127.0.0.1:8000): Use telnet ou nc (netcat) para testar a conectividade da porta a partir do servidor Nginx.

    telnet 127.0.0.1 8000
    nc -vz 127.0.0.1 8000
    

    Uma conexão bem-sucedida deve mostrar Connected to 127.0.0.1. ou succeeded!. Se travar ou mostrar Connection refused, o serviço upstream não está ouvindo ou um firewall está bloqueando.

  • Para sockets Unix (ex.: unix:/run/php/phpX.X-fpm.sock): Verifique se o arquivo de socket existe e tem as permissões corretas.

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

    O Nginx deve ter permissões de leitura/escrita neste arquivo de socket. O usuário do Nginx (ex.: www-data) precisa fazer parte do grupo que possui o socket (ex.: www-data ou php-fpm).

Causas Comuns e Soluções

Com base nas suas etapas de diagnóstico, aqui estão as causas mais frequentes de erros 502 e como resolvê-las.

1. Servidor Upstream Não Está em Execução ou Falhou

Causa: A aplicação para a qual o Nginx está tentando fazer proxy (ex.: PHP-FPM, Gunicorn, aplicação Node.js) não está em execução ou falhou.

Solução: Inicie ou reinicie o serviço upstream.

# Exemplo para PHP-FPM
sudo systemctl start php8.2-fpm
# Se já estiver em execução e você suspeitar de uma falha, reinicie:
sudo systemctl restart php8.2-fpm

# Para aplicações customizadas, use seus comandos específicos de início/reinício

Dica: Certifique-se de que seus serviços upstream estão configurados para iniciar automaticamente na inicialização do sistema. Para serviços systemd, use systemctl enable phpX.X-fpm.

2. Sobrecarga do Servidor Upstream / Exaustão de Recursos

Causa: O servidor upstream está sobrecarregado, ficando sem memória, CPU ou atingindo limites de processo, fazendo com que pare de responder ou recuse novas conexões.

Sintomas: Os logs de erro do Nginx podem mostrar connection refused ou upstream timed out intermitentemente, especialmente sob carga. Ferramentas de monitoramento do sistema (top, htop, free -h) mostram alto uso de recursos.

Soluções:

  • Para PHP-FPM: Ajuste as configurações do pool do PHP-FPM no arquivo de configuração (ex.: /etc/php/X.X/fpm/pool.d/www.conf).

    • pm.max_children: O número máximo de filhos que podem estar ativos ao mesmo tempo.
    • pm.start_servers: O número de filhos criados na inicialização.
    • pm.min_spare_servers, pm.max_spare_servers: Controla quantos filhos ociosos são mantidos.
    ; Exemplo para gerenciamento dinâmico de processos
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 10
    pm.min_spare_servers = 5
    pm.max_spare_servers = 20
    
    • Aumente memory_limit no php.ini se os scripts estiverem esgotando a memória.
  • Para outras aplicações: Aumente o número de processos workers, threads ou aloque mais memória, se possível. Monitore as métricas específicas da sua aplicação.

  • Timeouts do Nginx: Aumente as diretivas proxy_connect_timeout, proxy_send_timeout e proxy_read_timeout na configuração do Nginx, mas entenda que isso apenas atrasa o erro se o backend estiver realmente com dificuldades.

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

3. Configuração Incorreta do Upstream no Nginx

Causa: O Nginx está configurado para conectar ao endereço IP, porta ou caminho de socket Unix errado para o servidor upstream.

Sintomas: Os logs de erro do Nginx mostram connect() failed (111: Connection refused) imediatamente após uma requisição.

Solução: Revise cuidadosamente a configuração do bloco de servidor do Nginx (/etc/nginx/sites-available/your_site.conf).

  • Para upstreams HTTP/HTTPS:

    location /app {
        proxy_pass http://127.0.0.1:8000; # Certifique-se de que o IP e a porta estão corretos
        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 via socket Unix:

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/phpX.X-fpm.sock; # Verifique se este caminho corresponde exatamente à configuração do PHP-FPM
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    
  • Para PHP-FPM via TCP/IP:

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000; # Verifique o IP e a porta
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    

Após fazer alterações, sempre teste sua configuração do Nginx e recarregue/reinicie o Nginx:

nginx -t
systemctl reload nginx # Ou reinicie se -t indicar necessidade

4. request_terminate_timeout do PHP-FPM Excedido

Causa: Um script PHP leva mais tempo para executar do que a configuração request_terminate_timeout no PHP-FPM. O Nginx aguarda a resposta, mas o PHP-FPM termina o script, fazendo com que o Nginx receba uma resposta incompleta.

Sintomas: Os logs de erro do Nginx podem mostrar upstream timed out ou script timed out. Os logs do PHP-FPM podem mostrar child XX exited on signal 9 (SIGKILL).

Solução:

  • Aumente request_terminate_timeout: Na configuração do pool do PHP-FPM (www.conf), encontre e ajuste esta diretiva. Definir como 0 desativa o timeout, mas isso geralmente não é recomendado, pois scripts de longa duração podem travar recursos.

    request_terminate_timeout = 300 # Aumente para 5 minutos (300 segundos)
    
  • Aumente fastcgi_read_timeout no Nginx: Este timeout do Nginx deve ser igual ou maior que request_terminate_timeout.

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

Aviso: Embora aumentar os timeouts possa resolver o erro 502, isso pode mascarar problemas de desempenho subjacentes. A melhor solução a longo prazo é otimizar o script PHP lento.

5. Problemas de Firewall

Causa: Um firewall (no servidor Nginx ou no servidor upstream, se forem separados) está bloqueando conexões para a porta ou socket upstream.

Solução:

  • Verifique o status do firewall:

    sudo ufw status # Para UFW (Ubuntu/Debian)
    sudo firewall-cmd --list-all # Para firewalld (CentOS/RHEL)
    sudo iptables -L # Para iptables
    
  • Abra as portas necessárias: Certifique-se de que a porta que o Nginx usa para conectar ao upstream (ex.: 9000 para PHP-FPM via TCP/IP) está aberta.

    sudo ufw allow from 127.0.0.1 to any port 9000 # Permite que localhost se conecte à porta 9000
    sudo firewall-cmd --permanent --add-port=9000/tcp # Para firewalld
    sudo firewall-cmd --reload
    
  • Desative temporariamente o firewall para fins de teste apenas em um ambiente controlado, depois reative e configure-o corretamente.

6. Interferência do SELinux ou AppArmor

Causa: Aprimoramentos de segurança como SELinux (no RHEL/CentOS) ou AppArmor (no Ubuntu/Debian) podem estar impedindo o Nginx de acessar o socket upstream ou fazer conexões de rede, mesmo que as permissões de arquivo e firewalls estejam configurados corretamente.

Sintomas: Os logs podem mostrar permission denied ou mensagens semelhantes, especialmente em /var/log/audit/audit.log (para SELinux).

Solução:

  • Verifique audit.log:

    sudo grep nginx /var/log/audit/audit.log
    
  • Defina temporariamente o SELinux para modo permissivo: sudo setenforce 0. Se o erro for resolvido, o SELinux é o culpado. Você precisará gerar e aplicar políticas SELinux apropriadas (ex.: audit2allow). Lembre-se de definir de volta para enforcing (sudo setenforce 1).

  • Verifique o status do AppArmor: sudo aa-status. Se o AppArmor estiver ativo, pode ser necessário ajustar o perfil do Nginx.

7. Corpos de Requisição/Resposta Grandes (Buffer de Proxy)

Causa: As configurações padrão de buffer de proxy do Nginx podem ser muito pequenas para corpos de requisição ou resposta muito grandes, levando ao fechamento prematuro da conexão.

Sintomas: Os logs de erro do Nginx podem mostrar upstream prematurely closed connection while reading response header from upstream ou upstream prematurely closed connection while reading response body from upstream.

Solução: Ajuste as diretivas de buffer de proxy do Nginx no bloco http, server ou location.

http {
    ...
    proxy_buffer_size   128k; # Tamanho do buffer para a primeira parte da resposta
    proxy_buffers   4 256k; # Número e tamanho dos buffers para o resto da resposta
    proxy_busy_buffers_size   256k; # Tamanho máximo dos buffers ocupados
    proxy_temp_file_write_size 256k; # Tamanho para escrever em arquivos temporários se o buffer transbordar
    ...
}

Nota: Essas configurações consomem mais memória. Ajuste-as com cautela com base nos recursos do seu servidor e no tamanho típico das respostas da sua aplicação.

Dicas Gerais de Solução de Problemas

  • Revise todos os logs relevantes: Além dos logs de erro do Nginx, verifique também os logs de acesso do Nginx, logs da aplicação upstream (PHP-FPM, Gunicorn, logs da aplicação Node.js) e logs do sistema (/var/log/syslog, dmesg).
  • Reinicie o Nginx: Após qualquer alteração na configuração, sempre reinicie o Nginx para garantir que elas entrem em vigor: systemctl restart nginx.
  • Teste a Configuração do Nginx: Antes de reiniciar, valide a sintaxe da configuração do Nginx: nginx -t.
  • Isole o Problema: Tente ignorar o Nginx e acessar a aplicação upstream diretamente. Por exemplo, se sua aplicação Node.js estiver em localhost:3000, use curl http://localhost:3000 a partir da linha de comando do servidor. Se isso também falhar, o problema é definitivamente com sua aplicação, não com o Nginx.
  • Verifique o Espaço em Disco: Um disco cheio pode impedir que as aplicações escrevam arquivos temporários ou logs, levando a falhas ou travamentos. Use df -h para verificar o uso do disco.

Conclusão

Comece com /var/log/nginx/error.log, depois verifique se o upstream está em execução e acessível a partir do host Nginx. Depois de saber se a falha é conexão recusada, timeout, permissão negada ou fechamento prematuro, a correção geralmente está no serviço upstream, permissões de socket, configurações de timeout ou regra de firewall.