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.csse orootfor/var/www/site, o Nginx tenta ler/var/www/site/css/app.css. - Se a URL for
/, o Nginx procura um arquivo de índice (viaindex).
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:
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
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.htmlquando 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.';JS2) 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
denyouinternal(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
=404por 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
rootefetivo nolocation(umrootdentro delocationsobrescreve o do nível do server). - Se for SPA, use fallback para
/index.htmlnotry_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.jsouapp.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(ou304 Not Modifiedse houver cache/revalidação)Cache-Control: no-cache(se você configurou para HTML)- Possível presença de
Last-Modifiede/ouETag(ajudam na revalidação)
2) Testar headers de um asset (CSS/JS)
curl -I http://localhost/css/app.cssO que observar:
Cache-Controlcommax-agealto e possivelmenteimmutable- Header
Expirescoerente com o tempo configurado emexpires
3) Forçar um 404 para validar try_files
Teste uma URL inexistente:
curl -I http://localhost/nao-existe- Se seu
try_filesestiver com=404, espere404 Not Found. - Se seu
try_filesestiver com fallback para/index.html, espere200 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.cssO 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).