Ubuntu nginx
O nginx (pronuncia-se "engine-x") é um servidor web: o programa que recebe os pedidos do navegador e devolve as páginas. Ele também é muito usado como proxy reverso, a "recepção" que fica na frente de uma aplicação (Node, Python, PHP) e repassa os pedidos para ela.
- Como um pedido viaja do navegador até o nginx.
- Instalar o nginx e testá-lo com
curl. - Onde ficam as configurações e o que cada linha de um server block faz.
- Publicar um site, testar a configuração com
nginx -te aplicar comreload. - Ler os logs e resolver os erros 502, 403 e "porta ocupada".
Os exemplos acontecem na máquina fictícia servidor (IP 192.168.0.50), com a usuária ana. Para praticar, uma VM com Ubuntu Server ou o Multipass (multipass launch --name web) servem bem.
Conceito: o caminho de um pedido
- Você digita
http://meusite.com.brno navegador. - O DNS traduz o nome para o IP do servidor (veja Conceitos de Rede).
- O navegador se conecta à porta 80 (HTTP) ou 443 (HTTPS) desse IP.
- O nginx, que está "escutando" nessa porta, olha o nome pedido (
Host: meusite.com.br) e escolhe qual configuração (server block) usar. - Ele entrega um arquivo da pasta do site, ou repassa o pedido para uma aplicação (proxy reverso).
Um mesmo nginx pode atender dezenas de sites, cada um com seu server block. Isso se chama virtual hosts.
Instalar e testar
$ sudo apt install nginx $ systemctl is-active nginx active « já está rodando
Teste do próprio servidor com curl. A opção -I mostra só os cabeçalhos da resposta:
- curl
- Faz pedidos HTTP pelo terminal (veja curl, wget, dig).
- -I
- Pede só os cabeçalhos (head), sem o corpo da página.
- http://localhost
localhost= a própria máquina.
$ curl -I http://localhost HTTP/1.1 200 OK « 200 = deu certo Server: nginx/1.28.3 (Ubuntu) « quem respondeu Date: Thu, 15 Oct 2026 13:30:00 GMT Content-Type: text/html Content-Length: 615 Last-Modified: Thu, 15 Oct 2026 13:25:41 GMT Connection: keep-alive ETag: "6a0f7a85-267" Accept-Ranges: bytes
De outro computador da rede, abra http://192.168.0.50 no navegador: aparece a página "Welcome to nginx!". Se não abrir e o firewall estiver ligado, libere as portas (veja Firewall (ufw)):
$ sudo ufw allow 'Nginx Full' Regra adicionada Regra adicionada (v6)
Nginx Full é um perfil que o pacote instala: libera as portas 80 e 443. Também existem Nginx HTTP (só 80) e Nginx HTTPS (só 443). Veja todos com sudo ufw app list.
Onde fica cada coisa
| Caminho | O que é |
|---|---|
/etc/nginx/nginx.conf | Configuração principal. Raramente precisa mexer |
/etc/nginx/sites-available/ | Um arquivo por site: as configurações disponíveis |
/etc/nginx/sites-enabled/ | Atalhos (links) para os sites ativados. O nginx só lê esta pasta |
/etc/nginx/conf.d/ | Trechos extras de configuração (*.conf) |
/etc/nginx/snippets/ | Pedaços reaproveitáveis (ex.: configurações de SSL) |
/var/www/html/ | Pasta do site padrão |
/var/log/nginx/access.log | Registro de cada pedido |
/var/log/nginx/error.log | Registro de erros |
A ideia de sites-available + sites-enabled: você escreve o site em um lugar e o liga ou desliga criando ou apagando um atalho, sem perder a configuração.
$ ls -l /etc/nginx/sites-enabled/ total 0 lrwxrwxrwx 1 root root 34 Oct 15 13:25 default -> /etc/nginx/sites-available/default
Publicar o seu primeiro site
- Crie a pasta e uma página.
$ sudo mkdir -p /var/www/meusite $ echo '<h1>Olá do meu site!</h1>' | sudo tee /var/www/meusite/index.html <h1>Olá do meu site!</h1>
- Escreva o server block com
sudo nano /etc/nginx/sites-available/meusite:server { listen 80; # escuta na porta 80 (IPv4) listen [::]:80; # e também em IPv6 server_name meusite.local www.meusite.local; # nomes que este bloco atende root /var/www/meusite; # pasta com os arquivos do site index index.html; # arquivo aberto quando pedem só "/" location / { # tenta o arquivo, depois uma pasta com esse nome; se não achar, erro 404 try_files $uri $uri/ =404; } access_log /var/log/nginx/meusite.access.log; # log só deste site error_log /var/log/nginx/meusite.error.log; }Cada instrução termina com
;. Blocos ficam entre{ }. Linhas com#são comentários. - Ative o site criando o atalho:
$ sudo ln -s /etc/nginx/sites-available/meusite /etc/nginx/sites-enabled/
- Teste a configuração antes de aplicar. Nunca pule este passo:
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
- Aplique sem derrubar quem está conectado:
$ sudo systemctl reload nginx
- Teste. Como
meusite.localnão existe no DNS, diga aocurlqual nome usar com o cabeçalhoHost:$ curl -H "Host: meusite.local" http://localhost <h1>Olá do meu site!</h1>
Para testar no navegador do seu computador, adicione
192.168.0.50 meusite.localao/etc/hostsdo seu computador.
reload ou restart?
| Comando | O que faz | Quando usar |
|---|---|---|
sudo nginx -t | Só confere a sintaxe | Sempre, antes dos outros |
sudo systemctl reload nginx | Relê a configuração; conexões abertas continuam | Depois de mudar um site |
sudo systemctl restart nginx | Para e inicia de novo; derruba as conexões | Atualizações do nginx ou quando o reload não resolve |
sudo nginx -t && sudo systemctl reload nginx | Só recarrega se o teste passar | O jeito mais seguro, numa linha |
O && só roda o segundo comando se o primeiro der certo (código de saída 0). Assim, uma configuração quebrada nunca é aplicada.
Ler os logs
Cada pedido vira uma linha no access.log. Acompanhe ao vivo com tail -f enquanto abre o site no navegador:
$ sudo tail -f /var/log/nginx/meusite.access.log 192.168.0.15 - - [15/Oct/2026:13:41:07 -0300] "GET / HTTP/1.1" 200 28 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:144.0) Gecko/20100101 Firefox/144.0" 192.168.0.15 - - [15/Oct/2026:13:41:07 -0300] "GET /favicon.ico HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:144.0) Gecko/20100101 Firefox/144.0"
| Trecho | Significado |
|---|---|
192.168.0.15 | IP de quem pediu |
[15/Oct/2026:13:41:07 -0300] | Data e hora |
"GET / HTTP/1.1" | Método, caminho pedido e versão do protocolo |
200 / 404 | Código de resposta: 200 ok, 404 não encontrado |
28 | Tamanho da resposta em bytes |
"Mozilla/5.0 …" | Navegador de quem pediu (user agent) |
Combinando com o que você aprendeu em sort, uniq, cut, descubra quem mais acessa:
$ sudo cut -d ' ' -f 1 /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -3
412 192.168.0.15
87 192.168.0.23
9 203.0.113.44
Códigos de resposta mais comuns
| Código | Significado | Causa típica |
|---|---|---|
| 200 | OK | Tudo certo |
| 301 / 302 | Redirecionado | Ex.: de HTTP para HTTPS |
| 403 | Proibido | Permissão de arquivo ou pasta sem index |
| 404 | Não encontrado | Arquivo não existe na pasta root |
| 500 | Erro interno | A aplicação quebrou |
| 502 | Bad Gateway | A aplicação atrás do proxy está fora do ar |
| 504 | Gateway Timeout | A aplicação demorou demais para responder |
Proxy reverso: nginx na frente de uma aplicação
Aplicações em Node.js, Python ou Go costumam rodar numa porta alta, como 3000, e não devem ficar expostas direto. O nginx recebe na porta 80/443 e repassa para elas.
Para testar sem ter uma aplicação, o Python serve uma pasta na porta 3000:
$ echo 'Resposta da aplicação' > index.html $ python3 -m http.server 3000 --bind 127.0.0.1 Serving HTTP on 127.0.0.1 port 3000 (http://127.0.0.1:3000/) ...
Deixe esse terminal aberto. Em outro, crie /etc/nginx/sites-available/app:
server {
listen 80;
server_name app.local;
location / {
proxy_pass http://127.0.0.1:3000; # para onde repassar
proxy_set_header Host $host; # nome original pedido
proxy_set_header X-Real-IP $remote_addr; # IP real do visitante
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # http ou https
}
}
Sem os proxy_set_header, a aplicação acharia que todos os visitantes vêm de 127.0.0.1, porque quem fala com ela é o nginx.
$ sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/ $ sudo nginx -t && sudo systemctl reload nginx nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful $ curl -H "Host: app.local" http://localhost Resposta da aplicação « veio da porta 3000, passando pelo nginx
Com o site respondendo na porta 80 e um domínio apontando para o servidor, você coloca o cadeado em poucos minutos. Veja HTTPS (Let's Encrypt).
Quando não funciona
$ curl -I -H "Host: app.local" http://localhost HTTP/1.1 502 Bad Gateway $ sudo tail -1 /var/log/nginx/error.log 2026/10/15 13:55:02 [error] 2210#2210: *17 connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: app.local, request: "HEAD / HTTP/1.1", upstream: "http://127.0.0.1:3000/", host: "app.local"
O que aconteceu: o nginx funciona, mas a aplicação na porta 3000 não está rodando. "upstream" é o nome que o nginx dá para a aplicação de trás.
Como confirmar: ss -tlnp | grep 3000 não mostra nada.
Como resolver: inicie a aplicação (de preferência como serviço, veja Criar um Serviço) e confira se a porta do proxy_pass é a mesma da aplicação.
$ sudo tail -1 /var/log/nginx/meusite.error.log 2026/10/15 14:02:11 [error] 2210#2210: *21 directory index of "/var/www/meusite/" is forbidden, client: 192.168.0.15, server: meusite.local, request: "GET / HTTP/1.1", host: "meusite.local"
O que aconteceu: a pasta existe, mas não tem o arquivo do index (ex.: você chamou de Index.html ou home.html).
Outra causa comum aparece como open() "/home/ana/site/index.html" failed (13: Permission denied): o nginx roda como o usuário www-data e não consegue entrar na sua pasta pessoal (que no Ubuntu é drwxr-x---).
Como resolver: confira o nome do arquivo com ls /var/www/meusite. Mantenha sites em /var/www, e não na pasta pessoal. Teste o acesso como o nginx com sudo -u www-data cat /var/www/meusite/index.html.
$ sudo systemctl restart nginx Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details. $ sudo journalctl -u nginx -n 3 --no-pager Oct 15 14:10:22 servidor nginx[3112]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) Oct 15 14:10:22 servidor systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE Oct 15 14:10:22 servidor systemd[1]: nginx.service: Failed with result 'exit-code'.
O que aconteceu: outro programa já usa a porta 80. Geralmente o Apache, instalado junto com algum pacote.
Como confirmar:
$ sudo ss -tlnp 'sport = :80'
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("apache2",pid=1890,fd=4))
Como resolver: se não precisa do Apache: sudo systemctl disable --now apache2 e depois sudo systemctl start nginx.
nginx -t acusa erro de sintaxe
$ sudo nginx -t nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/meusite:12 nginx: configuration file /etc/nginx/nginx.conf test failed
O que aconteceu: falta um ; ou sobra/falta uma chave. O número no fim (:12) é a linha; o erro real costuma estar na linha anterior.
Como resolver: abra o arquivo direto na linha: sudo nano +11 /etc/nginx/sites-available/meusite. Como você não rodou o reload, o site que está no ar continua funcionando com a configuração antiga.
O que aconteceu: o nome pedido não bateu com nenhum server_name, e o nginx usou o site padrão (default).
Como resolver: confira o server_name e o nome que você usa no navegador. Se não precisa do site padrão, desative: sudo rm /etc/nginx/sites-enabled/default e recarregue.
Referência rápida
| Comando / instrução | O que faz |
|---|---|
sudo nginx -t | Testa a configuração |
sudo nginx -T | Testa e mostra a configuração completa que está valendo |
sudo systemctl reload nginx | Aplica mudanças sem derrubar conexões |
sudo ln -s ../sites-available/X /etc/nginx/sites-enabled/ | Ativa um site |
sudo rm /etc/nginx/sites-enabled/X | Desativa um site (a configuração fica guardada) |
listen 80; | Porta em que o bloco atende |
server_name a.com www.a.com; | Nomes que o bloco atende |
root /var/www/x; | Pasta dos arquivos |
index index.html; | Arquivo padrão de uma pasta |
location /caminho { … } | Regras para uma parte do site |
proxy_pass http://127.0.0.1:3000; | Repassa para uma aplicação |
return 301 https://$host$request_uri; | Redireciona (ex.: para HTTPS) |
Exercícios
1. Testar antes de aplicar
Complete para recarregar o nginx só se a configuração estiver correta:
2. Ativar um site
Complete para ativar o site loja:
3. Proxy reverso
Complete a instrução que repassa os pedidos para uma aplicação na porta 8080 da própria máquina:
4. O site retorna 502 Bad Gateway. Qual a causa mais provável?
5. Qual a diferença entre reload e restart?
Resumo
- Sites ficam em
/etc/nginx/sites-available/e são ativados com um link emsites-enabled/. - Um server block define porta (
listen), nomes (server_name) e pasta (root) ou destino (proxy_pass). - Sempre
sudo nginx -t && sudo systemctl reload nginx. - Logs em
/var/log/nginx/: oerror.logdiz o porquê de cada 403, 404 e 502. - Teste nomes sem DNS com
curl -H "Host: nome" http://localhost.