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.

Você vai aprender
  • 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 -t e aplicar com reload.
  • 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

  1. Você digita http://meusite.com.br no navegador.
  2. O DNS traduz o nome para o IP do servidor (veja Conceitos de Rede).
  3. O navegador se conecta à porta 80 (HTTP) ou 443 (HTTPS) desse IP.
  4. O nginx, que está "escutando" nessa porta, olha o nome pedido (Host: meusite.com.br) e escolhe qual configuração (server block) usar.
  5. 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

CaminhoO que é
/etc/nginx/nginx.confConfiguraçã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.logRegistro de cada pedido
/var/log/nginx/error.logRegistro 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

  1. 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>
  2. 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.

  3. Ative o site criando o atalho:
    $ sudo ln -s /etc/nginx/sites-available/meusite /etc/nginx/sites-enabled/
  4. 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
  5. Aplique sem derrubar quem está conectado:
    $ sudo systemctl reload nginx
  6. Teste. Como meusite.local não existe no DNS, diga ao curl qual nome usar com o cabeçalho Host:
    $ 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.local ao /etc/hosts do seu computador.

reload ou restart?

ComandoO que fazQuando usar
sudo nginx -tSó confere a sintaxeSempre, antes dos outros
sudo systemctl reload nginxRelê a configuração; conexões abertas continuamDepois de mudar um site
sudo systemctl restart nginxPara e inicia de novo; derruba as conexõesAtualizações do nginx ou quando o reload não resolve
sudo nginx -t && sudo systemctl reload nginxSó recarrega se o teste passarO 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"
TrechoSignificado
192.168.0.15IP 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 / 404Código de resposta: 200 ok, 404 não encontrado
28Tamanho 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ódigoSignificadoCausa típica
200OKTudo certo
301 / 302RedirecionadoEx.: de HTTP para HTTPS
403ProibidoPermissão de arquivo ou pasta sem index
404Não encontradoArquivo não existe na pasta root
500Erro internoA aplicação quebrou
502Bad GatewayA aplicação atrás do proxy está fora do ar
504Gateway TimeoutA 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
Próximo passo: HTTPS

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

502 Bad Gateway
$ 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.

403 Forbidden
$ 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.

O nginx não sobe: porta 80 ocupada
$ 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.

Aparece a página "Welcome to nginx!" em vez do seu site

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çãoO que faz
sudo nginx -tTesta a configuração
sudo nginx -TTesta e mostra a configuração completa que está valendo
sudo systemctl reload nginxAplica 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/XDesativa 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:

sudo nginx sudo systemctl reload nginx

2. Ativar um site

Complete para ativar o site loja:

sudo ln -s /etc/nginx/sites-available/loja /etc/nginx/

3. Proxy reverso

Complete a instrução que repassa os pedidos para uma aplicação na porta 8080 da própria máquina:

proxy_pass

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 em sites-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/: o error.log diz o porquê de cada 403, 404 e 502.
  • Teste nomes sem DNS com curl -H "Host: nome" http://localhost.