Entendendo os Blocos de Servidor do Nginx: Perguntas Comuns de Configuração

Entenda como funcionam os blocos de servidor do Nginx — como as requisições são associadas ao domínio correto, o que vai dentro de um bloco e como organizar configurações de múltiplos sites sem confusão.

Entendendo os Blocos de Servidor do Nginx: Perguntas Comuns de Configuração

Entender os blocos de servidor do Nginx é uma das maneiras mais rápidas de tornar sua configuração do Nginx menos misteriosa. Os blocos de servidor decidem qual site lida com uma requisição, quais nomes de domínio correspondem, quais arquivos são servidos e para onde o tráfego de proxy vai.

Se você hospeda mais de um domínio, redireciona HTTP para HTTPS ou executa aplicativos por trás do Nginx, os blocos de servidor são onde a maior parte desse roteamento começa.

O que é um Bloco de Servidor do Nginx?

Um bloco de servidor do Nginx é uma seção de configuração que define como o Nginx deve responder para uma combinação específica de endereço, porta e nome de host.

Um bloco de servidor básico para site estático se parece com isso:

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Isso diz ao Nginx para escutar na porta 80, corresponder requisições para example.com e www.example.com, servir arquivos do diretório público e retornar 404 quando um arquivo não for encontrado.

O nome "bloco de servidor" é comum no Nginx. Usuários do Apache podem conhecer uma ideia semelhante como host virtual. O propósito é o mesmo: permitir que um servidor web lide com vários sites ou aplicativos.

Os blocos de servidor geralmente são armazenados em /etc/nginx/sites-available/ e ativados com links simbólicos para /etc/nginx/sites-enabled/ em sistemas Debian e Ubuntu. Algumas distribuições usam /etc/nginx/conf.d/ em vez disso. O layout exato é menos importante do que saber quais arquivos são incluídos pelo nginx.conf.

Como o Nginx Escolhe o Bloco de Servidor Correto?

A seleção do Nginx acontece em etapas. Primeiro, ele considera o endereço IP e a porta da diretiva listen. Em seguida, compara o nome de host da requisição com server_name.

Se nenhum nome de host corresponder, o Nginx usa o servidor padrão para aquele endereço e porta. Você pode marcar um explicitamente:

server {
    listen 80 default_server;
    server_name _;
    return 444;
}

Algumas equipes usam um bloco padrão como este para descartar requisições não correspondentes. Outros retornam um 404 simples. A melhor escolha depende de suas preferências de registro e segurança.

Se você ainda está aprendendo, um 404 visível como padrão pode ser mais fácil de depurar do que return 444, porque 444 é um fechamento de conexão específico do Nginx e pode parecer um problema de rede do lado do cliente. Em produção, algumas equipes preferem o fechamento silencioso para hosts não correspondentes aleatórios. Qualquer escolha é aceitável se a equipe a entender.

Nomes exatos são preferidos em relação a nomes curinga. Por exemplo, api.example.com é mais específico que *.example.com. Nomes de servidor com regex são possíveis, mas devem ser raros porque são mais difíceis de ler e solucionar problemas.

Um erro comum é adicionar um novo domínio ao DNS, mas esquecer de adicioná-lo ao server_name. A requisição chega ao servidor, mas o Nginx a envia para o bloco padrão. Da perspectiva do usuário, o site errado aparece ou a requisição falha.

Outro erro comum é criar dois blocos que reivindicam o mesmo listen e server_name. O Nginx pode avisar sobre nomes de servidor conflitantes e ignorar um deles. Sempre teste a configuração após adicionar um site.

Use isso quando o site errado responder:

sudo nginx -T | grep -n "server_name"
curl -I -H 'Host: example.com' http://127.0.0.1/

nginx -T imprime a configuração completa carregada, incluindo arquivos incluídos. Isso geralmente é mais rápido do que abrir todos os arquivos em sites-enabled.

O que vai Dentro de um Bloco de Servidor?

Um bloco de servidor geralmente contém diretivas para correspondência de domínio, TLS, raiz do documento, registro, redirecionamentos e um ou mais blocos location.

Para um proxy reverso, o bloco pode se parecer com isso:

server {
    listen 443 ssl;
    server_name app.example.com;

    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:3000;
    }
}

Aqui, o Nginx termina o HTTPS e encaminha o tráfego para um aplicativo local na porta 3000. Isso é comum para aplicativos Node.js, Python, Ruby, Go e Java.

Se o aplicativo upstream precisar saber o esquema original ou o IP do cliente, essas linhas proxy_set_header são importantes. Sem elas, o aplicativo pode pensar que cada requisição veio de 127.0.0.1 via HTTP simples. Isso pode quebrar redirecionamentos, logs de auditoria, limites de taxa e URLs de retorno geradas.

Use caminhos de log claros ao hospedar vários sites:

access_log /var/log/nginx/app.example.com.access.log;
error_log /var/log/nginx/app.example.com.error.log;

Logs separados facilitam muito a solução de problemas. Quando cada site escreve em um único log de acesso, leva mais tempo para identificar qual domínio está falhando.

Para um host movimentado, isso também facilita a retenção. Você pode querer logs detalhados para uma API durante um incidente e logs mais leves para um site estático. Manter os arquivos separados oferece essa opção sem alterar todos os blocos de servidor de uma vez.

Como os Blocos de Servidor são Diferentes dos Blocos Location?

Os blocos de servidor escolhem o site. Os blocos location escolhem o que fazer com os caminhos dentro desse site.

Por exemplo:

server {
    server_name example.com;

    location /assets/ {
        expires 30d;
    }

    location /api/ {
        proxy_pass http://api_backend;
    }

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Requisições para /assets/logo.png obtêm cache de arquivo estático. Requisições para /api/users vão para um backend upstream. Outras requisições caem no aplicativo frontend.

Essa divisão é importante. Se o domínio errado responder, olhe para a correspondência do bloco de servidor. Se o domínio certo responder, mas o comportamento do caminho errado acontecer, olhe para a correspondência do bloco location.

Essa distinção economiza tempo. Uma requisição para api.example.com/users pode falhar porque api.example.com correspondeu ao bloco de servidor errado, ou porque /users correspondeu ao bloco location errado dentro do bloco certo. Esses são problemas diferentes.

Para mais detalhes sobre roteamento de caminhos, veja Blocos location do Nginx explicados.

Como Devo Organizar Vários Sites?

Use um arquivo por site ou aplicativo quando possível. Dê a cada arquivo um nome que corresponda ao domínio ou propósito:

/etc/nginx/sites-available/example.com
/etc/nginx/sites-available/api.example.com
/etc/nginx/sites-available/admin.example.com

Isso facilita as revisões e reduz a chance de alterar o serviço errado. Também ajuda quando você precisa desabilitar um site rapidamente.

Mantenha os snippets compartilhados pequenos e óbvios. Configurações de TLS, cabeçalhos de proxy e cabeçalhos de segurança são bons candidatos para includes. Evite esconder comportamento de roteamento principal em um arquivo include genérico, porque isso dificulta a depuração.

Uma configuração prática pode incluir:

include snippets/proxy-headers.conf;
include snippets/security-headers.conf;

Use includes para reduzir repetição, não para fazer todos os sites se comportarem de forma idêntica. Um painel de administração interno, uma API pública e um site de marketing estático geralmente precisam de limites e cabeçalhos diferentes.

Antes de excluir ou renomear um arquivo de bloco de servidor, verifique como ele é incluído. Em layouts estilo Debian, remover o arquivo de sites-available não faz nada se outra cópia ainda existir em conf.d. Por outro lado, excluir um link simbólico em sites-enabled desabilita o site sem excluir o arquivo de origem.

ls -l /etc/nginx/sites-enabled/
sudo nginx -T | grep -n "include"

Essa verificação rápida evita o caso frustrante em que você edita o arquivo de aparência correta e o Nginx continua usando um diferente.

Quando Pedir Ajuda com Problemas de Bloco de Servidor

Peça ajuda a um engenheiro DevOps ou especialista em Nginx quando alterações no bloco de servidor afetarem domínios de produção, certificados HTTPS, redirecionamentos voltados ao cliente ou vários aplicativos no mesmo host. Pequenos erros podem enviar usuários para o aplicativo errado ou quebrar a renovação do certificado.

Você também deve pedir ajuda se o Nginx continuar servindo o site errado depois que você achar que a configuração está correta. O problema pode envolver DNS, IPv6, um balanceador de carga, uma CDN ou um arquivo include que você não notou.

Os blocos de servidor são o mapa que o Nginx usa para rotear tráfego no nível do domínio. Mantenha-os específicos, teste após cada alteração, use logs separados e separe a correspondência de domínio do roteamento de caminhos em seu modelo mental. Quando isso fizer sentido, a maioria das perguntas de configuração do Nginx se tornará muito mais fácil de responder.