Servindo conteúdo estático com Nginx: root, index, try_files e cache de navegador

Capítulo 5

Tempo estimado de leitura: 8 minutos

+ Exercício

Objetivo: publicar um site estático com controle de fallback e cache

Neste capítulo você vai configurar um server block para servir arquivos estáticos (HTML/CSS/JS/imagens) com Nginx, entendendo como root, index e try_files determinam o que é entregue ao navegador. Também vai ajustar permissões e diagnosticar erros comuns (403 e 404), além de configurar cache de navegador com Cache-Control e expires, diferenciando HTML (curto/sem cache agressivo) de assets versionados (cache longo).

Diretivas-chave para conteúdo estático

root: onde o Nginx procura os arquivos

A diretiva root define o diretório base no sistema de arquivos. Quando o Nginx recebe uma requisição, ele combina o caminho da URL com o root para localizar o arquivo.

  • Se a URL for /css/app.css e o root for /var/www/site, o Nginx tenta ler /var/www/site/css/app.css.
  • Se a URL for /, o Nginx procura um arquivo de índice (via index).

index: arquivo padrão quando a URL aponta para um diretório

Quando a URL termina em / (ou aponta para um diretório), o Nginx tenta servir um dos arquivos listados em index, na ordem informada.

index index.html index.htm;

Se /var/www/site/ existir e tiver index.html, ele será servido para a URL /.

try_files: fallback e roteamento simples sem aplicação

try_files tenta encontrar arquivos (ou diretórios) em uma sequência e, se nada existir, faz fallback para outro destino (um arquivo, um código HTTP, ou uma URI interna). É a base para:

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

  • Evitar 404 desnecessário quando você quer fallback para uma página (ex.: 404.html).
  • Roteamento simples para sites estáticos com “rotas” (ex.: SPA) sem backend: servir sempre /index.html quando a rota não é um arquivo real.

Exemplo típico para SPA (React/Vue/Angular):

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

Interpretação:

  • Tenta servir o arquivo exato ($uri).
  • Se não existir, tenta como diretório ($uri/).
  • Se ainda não existir, serve /index.html.

Passo a passo: publicar uma pasta com HTML/CSS/JS

1) Criar a estrutura do site

Crie uma pasta para o site e alguns arquivos de exemplo:

sudo mkdir -p /var/www/site/{css,js,assets}sudo tee /var/www/site/index.html > /dev/null <<'HTML'<!doctype html><html><head>  <meta charset="utf-8">  <meta name="viewport" content="width=device-width, initial-scale=1">  <title>Site Estático</title>  <link rel="stylesheet" href="/css/app.css?v=1"></head><body>  <h1>Olá, Nginx</h1>  <div id="app"></div>  <script src="/js/app.js?v=1"></script></body></html>HTMLsudo tee /var/www/site/css/app.css > /dev/null <<'CSS'body { font-family: Arial, sans-serif; }h1 { color: #2b6cb0; }CSSsudo tee /var/www/site/js/app.js > /dev/null <<'JS'document.getElementById('app').textContent = 'JS carregado com sucesso.';JS

2) Ajustar permissões (evitar 403)

Para o Nginx conseguir ler os arquivos, o usuário do processo (comum: www-data em Debian/Ubuntu) precisa de permissão de leitura nos arquivos e permissão de execução (traversal) nos diretórios do caminho.

Uma configuração simples e segura para conteúdo estático:

sudo chown -R root:root /var/www/sitesudo find /var/www/site -type d -exec chmod 755 {} \;sudo find /var/www/site -type f -exec chmod 644 {} \;

Isso garante que qualquer usuário (incluindo o do Nginx) consiga ler arquivos e atravessar diretórios, sem permitir escrita pública.

3) Configurar o Nginx para servir o site

Edite o arquivo do seu site (o caminho exato depende de como você organiza seus arquivos). Dentro do server block correspondente, defina root, index e um location / com try_files.

root /var/www/site;index index.html;location / {    try_files $uri $uri/ =404;}

Nesse formato, o Nginx só serve arquivos existentes; se não existir, retorna 404. Se você quiser fallback para /index.html (roteamento simples de SPA), troque para:

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

4) Diagnóstico rápido de 403 e 404

Quando aparece 403 (Forbidden)

As causas mais comuns ao servir estático:

  • Permissões insuficientes: o Nginx não consegue ler o arquivo ou atravessar diretórios.
  • Diretório sem index: você acessa uma URL que aponta para um diretório e não há arquivo listado em index (e listagem de diretório normalmente está desativada).
  • Bloqueio por regra: alguma regra de deny ou internal (menos comum em site estático simples).

Checklist prático:

  • Confirme que o arquivo existe: ls -la /var/www/site
  • Confirme permissões do caminho inteiro: namei -l /var/www/site/index.html
  • Verifique se há index index.html; e se o arquivo existe.

Quando aparece 404 (Not Found)

As causas mais comuns:

  • Arquivo não existe no caminho montado por root + URI.
  • root incorreto (apontando para a pasta errada).
  • try_files retornando =404 por não encontrar nenhum candidato.

Checklist prático:

  • Teste o caminho real: para /css/app.css, verifique /var/www/site/css/app.css.
  • Confirme o root efetivo no location (um root dentro de location sobrescreve o do nível do server).
  • Se for SPA, use fallback para /index.html no try_files.

Cache de navegador: HTML vs assets

Por que diferenciar?

  • HTML muda com frequência e controla quais assets serão carregados. Se o HTML ficar cacheado por muito tempo, o usuário pode continuar apontando para assets antigos.
  • Assets versionados (com hash no nome ou query string, como app.3f2a1c.js ou app.js?v=1) podem ter cache longo, porque quando você muda o arquivo, muda a versão/URL.

Configurar cache para assets (longo)

Para arquivos estáticos como CSS/JS/imagens/fontes, você pode definir cache agressivo. Exemplo:

location ~* \.(css|js|png|jpg|jpeg|gif|svg|ico|webp|woff2?)$ {    expires 30d;    add_header Cache-Control "public, max-age=2592000, immutable";}

immutable é útil quando você usa versionamento no nome do arquivo (hash). Se você não versiona, evite immutable e use um tempo menor.

Configurar cache para HTML (curto ou sem cache)

Para evitar que o navegador “prenda” uma versão antiga do HTML, use cache curto ou desative:

location = /index.html {    expires -1;    add_header Cache-Control "no-cache";}

Se você tem múltiplas páginas HTML, pode aplicar a todos:

location ~* \.(html)$ {    expires -1;    add_header Cache-Control "no-cache";}

Observação: no-cache não significa “não armazenar”; significa “revalidar antes de usar”. Se você quer impedir armazenamento, use no-store, mas isso costuma ser mais restritivo do que o necessário para sites estáticos.

Exemplo completo (trecho) combinando root/index/try_files e cache

root /var/www/site;index index.html;location / {    try_files $uri $uri/ /index.html;}location ~* \.(css|js|png|jpg|jpeg|gif|svg|ico|webp|woff2?)$ {    expires 30d;    add_header Cache-Control "public, max-age=2592000, immutable";}location ~* \.(html)$ {    expires -1;    add_header Cache-Control "no-cache";}

Mini-lab: validar com curl -I e observar headers

1) Testar headers do HTML

Faça uma requisição apenas de cabeçalhos para a página:

curl -I http://localhost/

O que observar:

  • HTTP/1.1 200 OK (ou 304 Not Modified se houver cache/revalidação)
  • Cache-Control: no-cache (se você configurou para HTML)
  • Possível presença de Last-Modified e/ou ETag (ajudam na revalidação)

2) Testar headers de um asset (CSS/JS)

curl -I http://localhost/css/app.css

O que observar:

  • Cache-Control com max-age alto e possivelmente immutable
  • Header Expires coerente com o tempo configurado em expires

3) Forçar um 404 para validar try_files

Teste uma URL inexistente:

curl -I http://localhost/nao-existe
  • Se seu try_files estiver com =404, espere 404 Not Found.
  • Se seu try_files estiver com fallback para /index.html, espere 200 OK (útil para SPA).

4) Simular erro 403 por permissão (apenas para aprendizado)

Você pode simular um 403 removendo leitura de um arquivo e testando o acesso. Depois, desfaça a alteração.

sudo chmod 000 /var/www/site/css/app.csscurl -I http://localhost/css/app.csssudo chmod 644 /var/www/site/css/app.css

O esperado durante a permissão 000 é um 403 Forbidden. Se você não obtiver 403, revise qual arquivo está sendo servido (pode haver cache intermediário, ou você pode estar apontando para outro root).

Agora responda o exercício sobre o conteúdo:

Em um site estático do tipo SPA servido pelo Nginx, qual configuração de try_files atende ao objetivo de servir arquivos existentes e, quando a rota não corresponder a um arquivo real, fazer fallback para /index.html?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Para SPA, o Nginx deve tentar servir o arquivo solicitado ($uri) ou o diretório ($uri/) e, se nada existir, devolver /index.html como fallback, permitindo que o roteamento do front-end funcione.

Próximo capitúlo

Locations no Nginx: correspondência, precedência e boas práticas

Arrow Right Icon
Capa do Ebook gratuito Nginx para Iniciantes: Servidor Web, Reverse Proxy e Balanceamento Básico
38%

Nginx para Iniciantes: Servidor Web, Reverse Proxy e Balanceamento Básico

Novo curso

13 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.