A maior parte da investigação em NGINX é curta, desde que você comece no lugar certo. O problema é que o primeiro movimento óbvio — reiniciar e ver — é justamente o que perde informação e derruba conexões.

Teste antes de recarregar

nginx -t interpreta a configuração e reporta o primeiro problema com arquivo e número de linha. Não muda nada.

Rode antes de cada reload, sem exceção. Um reload com configuração quebrada é recusado, o que é seguro, mas você descobre no momento em que tentava mudar algo, e não no momento em que terminou de escrever.

Um reload não é um restart

Envie um reload e o processo master valida a nova configuração, e se estiver boa, sobe novos processos worker com ela. Os workers antigos param de aceitar novas conexões e seguem servindo as que já têm até terminarem, e então saem.

Nada em trânsito é derrubado. É por isso que mudanças de configuração em produção são rotina em vez de evento, e é a coisa mais útil a saber sobre operar NGINX.

Um restart para tudo e sobe de novo. Conexões morrem. É necessário quando o próprio master precisa mudar — um binário novo, ou uma diretiva que só o master lê na inicialização — e não fora disso.

Vale saber para a prova e para ler material mais antigo: reload é SIGHUP ao master, encerramento gracioso é SIGQUIT, encerramento imediato é SIGTERM, e reabertura de logs é SIGUSR1. Um gerenciador de serviços embrulha isso, mas os sinais são o que ele envia.

Reabrir logs

Rotacionar um log renomeando o arquivo não faz o NGINX escrever no arquivo novo. O worker mantém um descritor aberto e segue escrevendo no renomeado, então o arquivo novo fica vazio e o espaço em disco nunca é de fato recuperado.

A correção é dizer ao NGINX para reabrir seus logs depois da renomeação. Toda configuração sensata de logrotate para NGINX faz isso, que é por que funciona quando você não pensou a respeito, e por que falha em silêncio quando alguém rotaciona à mão.

Qual log responde qual pergunta

O log de erro guarda o motivo. Falhas ao subir, negativas de permissão, problemas de conexão com upstream, falhas de handshake TLS. Seu nível é configurável, e debug está disponível se a compilação suportar — mas seja deliberado, porque a saída de debug é enorme.

O log de acesso guarda o registro. Qual requisição, qual status, quanto tempo levou, qual o tamanho. É onde você aprende o que aconteceu.

A divisão vale ser internalizada: o log de acesso diz que uma requisição devolveu 502, e o log de erro diz por quê.

As primeiras quatro conferências

A configuração é válida? nginx -t, sempre primeiro.

Está rodando, e como quem? O master deve ser root e os workers a conta user. Um master ausente significa que nunca subiu, e o log de erro dirá por quê.

O worker consegue ler? Quase todo 403 que não é um deny explícito é problema de permissão do usuário worker — o caminho inteiro, não só o arquivo.

Qual location de fato casou? Para qualquer coisa de roteamento, essa é a pergunta, e a resposta frequentemente não é o bloco que você esperava. O comparador de location deste site roda o algoritmo de seleção documentado e mostra o percurso.

Dois códigos de status que vale ler direito

502 significa que o NGINX alcançou o upstream e recebeu algo inutilizável, ou não conseguiu conectar. O problema normalmente está atrás do NGINX, não nele.

504 significa que o upstream aceitou a conexão e não respondeu a tempo. Isso é timeout, e a correção é o upstream ser mais rápido ou o timeout ser maior — decidir qual é o trabalho de verdade.

O que quem estuda precisa saber de cor

nginx -t valida sem mudar nada e deve preceder cada reload. Um reload sobe novos workers com a nova configuração e deixa os antigos terminarem suas conexões existentes, então nada em trânsito é derrubado; um restart derruba conexões e só é necessário quando o próprio master precisa mudar. Reload é SIGHUP, encerramento gracioso SIGQUIT, imediato SIGTERM, reabertura de log SIGUSR1. Renomear um arquivo de log não redireciona a saída — o NGINX precisa ser avisado para reabrir. O log de erro guarda o motivo e o log de acesso guarda o registro. Para um 403 suspeite de permissões do usuário worker no caminho inteiro; um 502 significa que o upstream devolveu algo inutilizável ou estava inalcançável, e um 504 que não respondeu a tempo.