Módulo 7 · 7.2
Um servidor web com nginx
Módulo 7: Domínio, servidor web e https · Tempo de leitura: 12 minutos
Objetivo de aprendizagem: Após esta lição, saberá instalar o nginx, configurar um site e um proxy inverso com um server block, testar e recarregar uma configuração em segurança e definir corretamente as permissões da sua webroot.
Conceitos-chave: nginx, server block, sites-available e sites-enabled, conf.d, listen, server_name, root, index, try_files, default server, nginx -t, reload, proxy inverso, proxy_pass, Host, X-Forwarded-For, X-Forwarded-Proto, webroot, PHP-FPM
O que faz um servidor web
Um servidor web escuta na porta 80 (http) e 443 (https), recebe pedidos dos navegadores e devolve algo: um ficheiro do disco (um site estático) ou a resposta de um programa que corre por trás (PHP, uma aplicação Node.js, um contentor). Neste segundo caso, o servidor web chama-se proxy inverso (reverse proxy): fica à frente, trata do https e passa o pedido à aplicação, que só escuta em 127.0.0.1.
Em Linux, o nginx e o Apache são os servidores web mais conhecidos, e o Caddy (lição 7.4) é uma alternativa moderna que trata dos certificados sozinho. Esta lição utiliza o nginx: está presente em todas as distribuições, consome pouca memória e é o padrão em muitos guias.
Instalar e primeiro olhar
anna@web1:~$ sudo apt install nginx
anna@web1:~$ systemctl status nginx
anna@web1:~$ curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.26.3
Content-Type: text/html(O número de versão é um exemplo.) Não se esqueça da firewall: as portas 80 e 443 têm de estar abertas (lição 5.2). Se abrir agora http://192.0.2.10, verá a página de boas-vindas do nginx.
A configuração encontra-se em /etc/nginx/:
| Caminho | O quê |
|---|---|
nginx.conf | ficheiro principal; normalmente não lhe mexe |
sites-available/ | um ficheiro por site (Debian e Ubuntu) |
sites-enabled/ | ligações (symlinks) para os sites ativos |
conf.d/*.conf | definições avulsas que são sempre carregadas |
snippets/ | excertos que reutiliza em vários sites |
sites-available e sites-enabled são um hábito do Debian e do Ubuntu: assim ativa ou desativa um site criando ou removendo uma ligação, sem apagar o ficheiro.
Um primeiro site
Crie uma pasta para o site e uma página de teste:
anna@web1:~$ sudo mkdir -p /var/www/example.com
anna@web1:~$ echo '<h1>Het werkt</h1>' | sudo tee /var/www/example.com/index.htmlCrie depois um server block: a descrição de um site.
# /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}Leia-o assim:
listen 80;elisten [::]:80;fazem o nginx escutar em IPv4 e em IPv6. Se esquecer a segunda linha, o seu registo AAAA não funciona (lição 7.1).server_nameindica para que nomes este bloco é válido. Em cada pedido, o nginx verifica o nome que o navegador pede (o cabeçalho Host) e escolhe o bloco correspondente.rooté a pasta com os ficheiros,indexo ficheiro mostrado quando se pede uma pasta.try_filestenta o ficheiro pedido, depois uma pasta, e caso contrário devolve um 404. Sem uma linha destas, uma configuração errada pode mostrar mais do que pretende.- Ficheiros de registo próprios por site facilitam muito a pesquisa (lição 6.2).
Ative o site, remova o site predefinido, teste e recarregue:
anna@web1:~$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
anna@web1:~$ sudo rm /etc/nginx/sites-enabled/default
anna@web1:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
anna@web1:~$ sudo systemctl reload nginx
anna@web1:~$ curl -I http://example.com
HTTP/1.1 200 OKFaça de nginx -t antes de cada reload um hábito fixo. Em caso de erro, indica-lhe o ficheiro e a linha, e o site em execução não é afetado. Se reiniciar sem testar, o nginx com um erro deixa de arrancar e todos os seus sites ficam em baixo (lição 6.1).
O default server: o que recebe um nome desconhecido?
O que acontece se alguém aceder ao seu servidor com um nome que não consta de nenhum server_name, ou simplesmente pelo endereço IP? Nesse caso, o nginx escolhe o default server: o bloco com default_server a seguir a listen ou, caso contrário, o primeiro bloco que encontrou. Sem pensar nisso, será portanto um dos seus sites reais.
Mais correto é um bloco separado que rejeita esses pedidos:
# /etc/nginx/sites-available/000-default
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}444 é um código especial do nginx: a ligação é fechada sem resposta. Os scanners que percorrem endereços IP não veem assim nada. Para https (porta 443), um default server funciona de forma um pouco diferente, porque precisa de um certificado; voltaremos a esse tema na lição 7.3.
O nginx como proxy inverso
Se tiver uma aplicação a correr em 127.0.0.1:3000 (lição 6.3) ou um contentor em 127.0.0.1:3001 (lição 9.3), o nginx disponibiliza-os para o exterior:
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}As quatro linhas proxy_set_header são importantes. Sem Host, a aplicação não sabe com que nome está a ser visitada. Sem X-Forwarded-For, a aplicação vê todas as visitas a chegar de 127.0.0.1 (o proxy) em vez do endereço real do visitante. Sem X-Forwarded-Proto, a aplicação julga que tudo passa por http e por vezes cria ligações ou cookies para http, embora o seu site funcione em https. Muitas aplicações têm uma definição para confiar nestes cabeçalhos ("trusted proxy"); indique aí apenas 127.0.0.1, caso contrário qualquer visitante pode enviar um endereço falso.
As aplicações que utilizam websockets (atualizações em tempo real, como o Uptime Kuma) precisam ainda de duas linhas: proxy_http_version 1.1; e a passagem de Upgrade e Connection. A documentação da aplicação costuma indicar exatamente quais.
Permissões da webroot
No Debian e no Ubuntu, o nginx executa os seus processos de trabalho como o utilizador www-data. Este tem de conseguir ler os seus ficheiros, mas não deve conseguir escrever neles. Uma boa organização (lição 3.1):
anna@web1:~$ sudo chown -R anna:www-data /var/www/example.com
anna@web1:~$ sudo find /var/www/example.com -type d -exec chmod 750 {} \;
anna@web1:~$ sudo find /var/www/example.com -type f -exec chmod 640 {} \;O utilizador (anna) gere os ficheiros, o grupo www-data pode ler e os restantes nada. Se o site precisar de escrever algures, como numa pasta de uploads, dê permissões de escrita a www-data apenas nessa pasta. Nunca chmod 777 (lição 10.2). Se obtiver um 403 Forbidden, consulte o registo de erros do site: aí aparece permission denied com o caminho.
Alguns outros hábitos:
- Nenhum segredo na webroot. Cópias de segurança (
site.zip), ficheiros.enve pastas.gitnão pertencem aí; se forem lá colocados por engano, podem ser descarregados. Uma rede de segurança adicional:location ~ /\. { deny all; }bloqueia todos os ficheiros que começam por um ponto (exceto o que permitir explicitamente, como/.well-known/, ver lição 7.3 e 7.4). - Ocultar a versão.
server_tokens off;emnginx.confretira o número de versão do cabeçalhoServere das páginas de erro. Não é verdadeira segurança, mas dá menos informação aos scanners.
PHP, em resumo
Para sites PHP (como o WordPress), o nginx comunica com o PHP-FPM, um serviço separado. No Debian, instala php-fpm e coloca no server block um bloco location ~ \.php$ com include snippets/fastcgi-php.conf; e fastcgi_pass unix:/run/php/php8.4-fpm.sock; (o número de versão varia consoante a versão da distribuição). O curso de WordPress aprofunda este tema.
No AlmaLinux e no Rocky Linux
Aí não existe sites-available: coloca cada site num ficheiro próprio em /etc/nginx/conf.d/<naam>.conf. O nginx corre como o utilizador nginx em vez de www-data, e a webroot predefinida é /usr/share/nginx/html. Por predefinição, o SELinux não permite que o nginx se ligue a uma aplicação por trás de proxy_pass; ative isso com setsebool -P httpd_can_network_connect 1. Ficheiros fora das pastas habituais precisam de uma etiqueta SELinux (semanage fcontext e restorecon).
Resumo
- O nginx serve ficheiros ou, como proxy inverso, passa pedidos a uma aplicação em
127.0.0.1. - Um server block por site em
sites-available, ativado com uma ligação emsites-enabled; escute em80e em[::]:80. - Sempre
nginx -tantes desystemctl reload nginx. - Um default server próprio com
return 444evita que um nome desconhecido ou o endereço IP simples mostre um dos seus sites. - Como proxy inverso, passa
Host,X-Forwarded-ForeX-Forwarded-Proto; a webroot é legível parawww-data, sem permissão de escrita e sem segredos.
Questionário
Exercício
Exercício O7.2: O seu primeiro site. Instale o nginx (ou utilize o Caddy da lição 7.4), crie um server block para um (sub)domínio que aponte para o seu servidor, com listen para IPv4 e IPv6, ficheiros de registo próprios e um default server próprio. Teste com nginx -t, recarregue e verifique com curl -I por IPv4 e IPv6. Defina as permissões da webroot como na lição. Preencha a lista de verificação e cole o seu server block.
Exercício O7.2: O seu primeiro site
Este exercício faz você mesmo; ninguém o verifica. Assinale o que já fez e marque o exercício como concluído.
No IP sem nome, nada (ligação fechada) ou uma página neutra, nunca o site de um cliente. Apenas uma pasta de uploads com permissão de escrita para www-data, o resto só de leitura. Atrás de um proxy: Host, X-Real-IP, X-Forwarded-For e X-Forwarded-Proto.
As suas marcações e notas ficam apenas neste navegador; não as enviamos para lado nenhum. Se tiver sessão iniciada, guardamos em Os meus cursos apenas que concluiu o exercício.
Para saber mais
- Forbidden (403): Não tem permissão para aceder a / neste servidor
- Documentação do nginx, How nginx processes a request (server_name e default server): https://nginx.org/en/docs/http/request_processing.html
- Documentação do nginx, Beginner's Guide: https://nginx.org/en/docs/beginners_guide.html
- Documentação do nginx,
ngx_http_proxy_module: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
