---
title: "Hospedar site estático React com Vite na VPS usando Nginx"
description: "Publique um site React ou Vite na VPS: npm run build, pasta dist, Nginx com try_files para rotas SPA, cache dos assets, gzip, HTTPS e deploy automático."
url: "https://streethosting.com.br/guias/vps/hospedar-site-estatico-react-vite-nginx"
category: "vps"
slug: "hospedar-site-estatico-react-vite-nginx"
datePublished: "2026-11-13"
dateModified: "2026-11-13"
author: "Equipe StreetHosting"
difficulty: "iniciante"
language: "pt-BR"
keywords:
  - "hospedar site react vps nginx"
  - "deploy vite nginx"
  - "nginx try_files spa"
  - "publicar pasta dist vps"
  - "cache assets nginx vite"
  - "site estático na vps"
---

# Como hospedar um site React com Vite na VPS: dist, Nginx, cache e deploy

Um site feito com Vite vira uma pasta de arquivos, e o Nginx entrega essa pasta muito bem. Veja o build, o server block com try_files para as rotas, o cache certo para cada arquivo, o HTTPS e um deploy automático.

> **Resposta rápida**
>
> Rode `npm run build` para gerar a pasta `dist`, envie o conteúdo dela para `/var/www/site` na VPS e aponte um server block do Nginx para essa pasta com `root`. Para as rotas do React funcionarem ao recarregar a página, use `try_files $uri $uri/ /index.html`. Dê cache longo aos arquivos de `/assets/`, que têm hash no nome, e nenhum cache ao `index.html`. Não é preciso instalar Node na VPS.

## O que o build entrega

Um projeto React criado com Vite só roda como código de desenvolvimento enquanto você usa o `npm run dev`. Para publicar, o `npm run build` compila tudo e escreve a pasta `dist`:

```
dist/
  index.html
  favicon.svg
  assets/
    index-DiwrgTda.js
    index-B3kQ91xe.css
```

Isso é um site estático comum: HTML, CSS, JavaScript e imagens. Não existe processo para manter rodando, porta para escutar nem linguagem para instalar na VPS. O Nginx lê os arquivos do disco e os entrega, uma tarefa rápida que gasta pouquíssima memória. Repare também no nome dos arquivos de `assets`: o trecho aleatório é um hash do conteúdo, e ele muda sempre que o arquivo muda. Essa característica é o que permite o cache agressivo mais adiante.

> **Atenção**
>
> Variáveis do Vite que começam com `VITE_` são copiadas para dentro do JavaScript no momento do build, e qualquer visitante lê. Use essas variáveis só para valores públicos, como a URL da sua API. Chave privada, token e senha ficam em um backend.

## Gerar o build e enviar para a VPS

No seu computador, na pasta do projeto:

```
npm ci
npm run build
```

Na VPS, instale o Nginx e prepare a pasta do site. Dê a posse da pasta ao usuário que vai enviar os arquivos e deixe o grupo do Nginx como grupo, para ele conseguir ler:

```
sudo apt update
sudo apt install -y nginx

sudo mkdir -p /var/www/site
sudo chown -R $USER:www-data /var/www/site
sudo chmod -R 755 /var/www/site
```

Agora envie o conteúdo da pasta `dist`. Há três jeitos, do mais simples ao mais repetível:

1. **Programa gráfico:** com o WinSCP ou o FileZilla, arraste o conteúdo de `dist` para `/var/www/site`. O passo a passo está no guia de [WinSCP e FileZilla com SFTP](https://streethosting.com.br/guias/vps/winscp-filezilla-sftp-vps).
2. **scp:** `scp -r dist/* usuario@IP_DA_VPS:/var/www/site/`, no terminal do Linux ou do Mac. No Windows, o caminho mais simples é o programa gráfico do item anterior.
3. **rsync:** `rsync -avz --delete dist/ usuario@IP_DA_VPS:/var/www/site/`. Envia só o que mudou e, com o `--delete`, remove da VPS os arquivos que não existem mais no build. O Windows não traz o rsync, então use o WSL ou o GitHub Actions da seção de deploy automático.

A barra final em `dist/` importa no rsync: com ela, o conteúdo da pasta vai para dentro de `/var/www/site`. Sem ela, ele criaria `/var/www/site/dist`. O guia de [transferir arquivos com scp e rsync](https://streethosting.com.br/guias/vps/transferir-arquivos-vps-scp-rsync) explica cada opção.

## Server block do Nginx

Antes, aponte o DNS do domínio para o IP da VPS, como no guia de [apontar um domínio para a VPS](https://streethosting.com.br/guias/vps/apontar-dominio-vps-registro-dns). Depois crie o arquivo `/etc/nginx/sites-available/site`:

```
server {
    listen 80;
    server_name meusite.com.br www.meusite.com.br;

    root /var/www/site;
    index index.html;

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

```
sudo ln -s /etc/nginx/sites-available/site /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```

O `root` diz onde estão os arquivos. O `try_files` tenta, nesta ordem, um arquivo com o caminho pedido, uma pasta com esse nome e, por último, o `/index.html`. Esse último passo é o que faz uma SPA funcionar.

Sem ele, quem abre o site pela raiz e navega pelos links do React não nota nada, porque o JavaScript troca a tela sem pedir nada ao servidor. O problema aparece quando a pessoa recarrega em `/sobre` ou abre um link direto para ela: o Nginx procura um arquivo `/var/www/site/sobre`, não acha e devolve 404. Com o fallback, ele entrega o index.html, o React carrega e resolve a rota sozinho.

> **Dica**
>
> Se o seu roteador usa o hash na URL (o endereço tem um # antes do caminho), o servidor nunca vê a rota e o try_files não é necessário. Se o site fica em uma subpasta, como `/app/`, defina também a opção `base` no `vite.config`, e o `location` do Nginx precisa acompanhar.

## Cache e gzip

Cada tipo de arquivo pede um cache diferente. Os arquivos de `assets` têm o hash no nome, então um arquivo com aquele nome nunca muda: dá para pedir ao navegador que o guarde por um ano. O `index.html` tem sempre o mesmo nome e aponta para os arquivos da versão atual, portanto precisa ser conferido a cada visita.

| Arquivo | Cache | Motivo |
| --- | --- | --- |
| /assets/ (JS, CSS, fontes com hash) | 1 ano, immutable | O nome muda quando o conteúdo muda, então nunca fica velho |
| index.html | Revalidar a cada visita | Aponta para os assets da versão atual e precisa ser revalidado |
| Imagens e ícones sem hash na pasta public | Cache curto, de dias | O nome continua igual quando o arquivo muda |

O server block completo, com cache e gzip:

```
server {
    listen 80;
    server_name meusite.com.br www.meusite.com.br;

    root /var/www/site;
    index index.html;

    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/css text/javascript application/javascript application/json image/svg+xml text/plain;

    location /assets/ {
        add_header Cache-Control "public, max-age=31536000, immutable";
        try_files $uri =404;
    }

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

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

- **location /assets/ com =404:** um arquivo de assets que não existe deve dar 404, e não receber o index.html. Se o fallback valesse aqui, o navegador receberia HTML no lugar do JavaScript e mostraria um erro confuso.
- **location = /index.html:** o fallback do try_files redireciona internamente para o index.html, então este bloco cobre a raiz do site e todas as rotas do React com o cabeçalho de não cachear.
- **gzip:** o Nginx já comprime o HTML por padrão quando o gzip está ligado. A lista de tipos inclui CSS, JavaScript, JSON e SVG, que são texto e encolhem bastante. Imagens como PNG e JPG já são comprimidas e não entram.

Teste com `curl -I https://meusite.com.br/assets/ARQUIVO.js` e confira o `cache-control` na resposta. Para ver o gzip, use `curl -sI -H "Accept-Encoding: gzip" URL` e procure `content-encoding: gzip`.

> **Atenção**
>
> Se você apagar a pasta antiga a cada deploy, quem estava com a página aberta pode pedir um arquivo antigo que não existe mais e receber 404 até recarregar. É raro e passa com um refresh. Para quem não quer isso, envie sem o `--delete` e limpe os assets antigos de tempos em tempos.

## HTTPS

Com o domínio apontando para a VPS e o site abrindo em HTTP, instale o certificado gratuito do Let's Encrypt. Pelo certbot:

```
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d meusite.com.br -d www.meusite.com.br
```

O certbot edita o arquivo do site, acrescenta o bloco da porta 443 e o redirecionamento de HTTP para HTTPS, e programa a renovação automática. Os detalhes e a verificação da renovação estão no guia de [certificado SSL com Let's Encrypt no Nginx](https://streethosting.com.br/guias/vps/certificado-ssl-vps-lets-encrypt-nginx). Depois do certbot, confira se o seu cache e o gzip continuam no bloco do 443, e que o `sudo nginx -t` passa. Se o site também fala com uma API sua, o mesmo server block pode repassar um caminho como `/api/` para o backend, como mostra o guia de [Nginx como proxy reverso](https://streethosting.com.br/guias/vps/configurar-nginx-reverse-proxy-vps), o que evita configurar CORS.

## Deploy automático

Enviar à mão funciona, mas a conta fecha melhor quando cada push na branch principal publica o site sozinho. O GitHub Actions faz o build na nuvem e envia a pasta para a VPS por rsync. Primeiro, crie uma chave SSH só para isso, sem senha, coloque a parte pública no `~/.ssh/authorized_keys` do usuário da VPS e guarde a parte privada em **Settings, Secrets and variables, Actions** do repositório, com os nomes abaixo.

- `VPS_HOST`: o IP ou o domínio da VPS.
- `VPS_USER`: o usuário do SSH.
- `VPS_SSH_KEY`: o conteúdo da chave privada.

Depois crie o arquivo `.github/workflows/deploy.yml` no projeto:

```
name: Deploy do site

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm

      - run: npm ci
      - run: npm run build

      - name: Enviar para a VPS
        env:
          VPS_HOST: ${{ secrets.VPS_HOST }}
          VPS_USER: ${{ secrets.VPS_USER }}
          VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
        run: |
          mkdir -p ~/.ssh
          echo "$VPS_SSH_KEY" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan -H "$VPS_HOST" >> ~/.ssh/known_hosts
          rsync -az --delete dist/ "$VPS_USER@$VPS_HOST:/var/www/site/"
```

A cada push em main, o Actions instala as dependências, gera o build e sincroniza a pasta. O usuário do SSH precisa ter permissão de escrita em `/var/www/site`, que foi o que o `chown` da seção de envio resolveu. Para variações, como restringir a chave a um único comando, veja o guia de [deploy com GitHub Actions na VPS](https://streethosting.com.br/guias/vps/deploy-github-actions-vps).

Se o seu projeto usa variáveis `VITE_` públicas, passe os valores no passo do build com a chave `env`, porque elas são lidas na hora em que o `npm run build` roda.

## Quando você nem precisa de VPS

Vamos ser diretos: um site estático puro, sem backend, não precisa de VPS. Existem serviços de hospedagem estática gratuitos que publicam essa pasta com HTTPS e CDN prontos, e fazem o deploy a cada push sem você configurar servidor. Para uma página de portfólio, uma landing page ou um projeto de estudo, esses serviços são o caminho mais curto.

A VPS passa a fazer sentido quando:

- **Você já tem uma VPS** com outras coisas rodando, e mais um server block no Nginx não custa nada a mais.
- **O site conversa com um backend seu** no mesmo domínio, como uma API em Node, Python ou Go, e você quer tudo atrás do mesmo Nginx, sem CORS.
- **Você quer controle total** de cabeçalhos, redirecionamentos, logs e regras, sem limites de plano de uma plataforma.
- **Você hospeda vários sites e projetos** e prefere um servidor só, com um custo fixo.

Um limite honesto do formato: uma SPA entrega um HTML quase vazio e monta a tela no navegador. Para site que depende de busca no Google, o conteúdo pode ser indexado com mais dificuldade do que em uma página renderizada no servidor. Se isso importa para você, considere um framework com renderização no servidor ou pré renderização, como o [Next.js na VPS](https://streethosting.com.br/guias/vps/hospedar-nextjs-vps).

## Onde rodar isso

Para o Nginx entregar arquivos, qualquer VPS Linux serve, e um site estático consome pouquíssimos recursos. Nas [VPS da StreetHosting](https://streethosting.com.br/vps) você tem acesso root para instalar o Nginx e o certbot, e a VPS Xeon a partir de R$ 26,00 por mês, com 2 vCPU, 2 GB DDR4 e 20 GB NVMe, comporta vários sites estáticos ao lado de uma API pequena.

Todas as VPS ficam em São Paulo, o que ajuda no tempo de resposta para visitantes no Brasil, com AntiDDoS incluso, até 5 TB de tráfego por mês e ativação em cerca de 60 segundos depois do Pix ou do cartão aprovado.

## Perguntas frequentes

### Por que minhas rotas dão 404 quando atualizo a página?

Em um site React com rotas no navegador, como o /sobre, esse caminho não existe como arquivo no servidor. O Nginx precisa devolver o index.html para qualquer caminho que não seja um arquivo real, e quem resolve a rota é o React. Isso se faz com try_files $uri $uri/ /index.html.

### Preciso instalar Node na VPS para hospedar um site Vite?

Não. O build gera arquivos HTML, CSS e JavaScript comuns, e o Nginx só entrega esses arquivos. O Node é necessário na máquina onde você roda o npm run build, que pode ser o seu computador ou o GitHub Actions.

### Por que não posso cachear o index.html por muito tempo?

O index.html aponta para os arquivos com hash no nome, como index-Ab12Cd.js. Se ele ficar guardado no navegador, o visitante continua carregando a versão antiga depois de um deploy. Os arquivos da pasta assets podem ter cache longo porque o nome muda a cada build, mas o index.html deve ser revalidado sempre.

### Posso colocar variáveis secretas no .env do Vite?

Não. Tudo que começa com VITE_ é copiado para dentro do JavaScript durante o build e qualquer visitante consegue ler. Chave de API privada precisa ficar em um backend, nunca no site estático.

### O site estático precisa mesmo de uma VPS?

Não precisa. Serviços de hospedagem estática gratuitos entregam bem um site assim. A VPS vale a pena quando você já tem uma, quer um backend no mesmo domínio, precisa de controle sobre cabeçalhos e redirecionamentos ou quer reunir vários projetos em um servidor só.

## Guias relacionados

- [Como configurar o Nginx como reverse proxy na VPS](https://streethosting.com.br/guias/vps/configurar-nginx-reverse-proxy-vps.md)
- [Certificado SSL na VPS com Let's Encrypt e Nginx](https://streethosting.com.br/guias/vps/certificado-ssl-vps-lets-encrypt-nginx.md)
- [Deploy com GitHub Actions na VPS: pipeline passo a passo](https://streethosting.com.br/guias/vps/deploy-github-actions-vps.md)
- [Como transferir arquivos para a VPS com SCP e rsync](https://streethosting.com.br/guias/vps/transferir-arquivos-vps-scp-rsync.md)
- [Como apontar domínio para VPS: registros A, AAAA e CNAME](https://streethosting.com.br/guias/vps/apontar-dominio-vps-registro-dns.md)

## Produtos citados

- https://streethosting.com.br/vps

## Dados estruturados

```json
[
  {
    "@context": "https://schema.org",
    "@type": [
      "Article",
      "TechArticle"
    ],
    "headline": "Como hospedar um site React com Vite na VPS: dist, Nginx, cache e deploy",
    "name": "Hospedar site estático React com Vite na VPS usando Nginx",
    "abstract": "Um site feito com Vite vira uma pasta de arquivos, e o Nginx entrega essa pasta muito bem. Veja o build, o server block com try_files para as rotas, o cache certo para cada arquivo, o HTTPS e um deploy automático.",
    "description": "Publique um site React ou Vite na VPS: npm run build, pasta dist, Nginx com try_files para rotas SPA, cache dos assets, gzip, HTTPS e deploy automático.",
    "datePublished": "2026-11-13",
    "dateModified": "2026-11-13",
    "author": {
      "@type": "Organization",
      "name": "Equipe StreetHosting"
    },
    "publisher": {
      "@type": "Organization",
      "name": "StreetHosting",
      "url": "https://streethosting.com.br"
    },
    "inLanguage": "pt-BR",
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://streethosting.com.br/guias/vps/hospedar-site-estatico-react-vite-nginx"
    }
  },
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {
        "@type": "Question",
        "name": "Por que minhas rotas dão 404 quando atualizo a página?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Em um site React com rotas no navegador, como o /sobre, esse caminho não existe como arquivo no servidor. O Nginx precisa devolver o index.html para qualquer caminho que não seja um arquivo real, e quem resolve a rota é o React. Isso se faz com try_files $uri $uri/ /index.html."
        }
      },
      {
        "@type": "Question",
        "name": "Preciso instalar Node na VPS para hospedar um site Vite?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Não. O build gera arquivos HTML, CSS e JavaScript comuns, e o Nginx só entrega esses arquivos. O Node é necessário na máquina onde você roda o npm run build, que pode ser o seu computador ou o GitHub Actions."
        }
      },
      {
        "@type": "Question",
        "name": "Por que não posso cachear o index.html por muito tempo?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "O index.html aponta para os arquivos com hash no nome, como index-Ab12Cd.js. Se ele ficar guardado no navegador, o visitante continua carregando a versão antiga depois de um deploy. Os arquivos da pasta assets podem ter cache longo porque o nome muda a cada build, mas o index.html deve ser revalidado sempre."
        }
      },
      {
        "@type": "Question",
        "name": "Posso colocar variáveis secretas no .env do Vite?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Não. Tudo que começa com VITE_ é copiado para dentro do JavaScript durante o build e qualquer visitante consegue ler. Chave de API privada precisa ficar em um backend, nunca no site estático."
        }
      },
      {
        "@type": "Question",
        "name": "O site estático precisa mesmo de uma VPS?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Não precisa. Serviços de hospedagem estática gratuitos entregam bem um site assim. A VPS vale a pena quando você já tem uma, quer um backend no mesmo domínio, precisa de controle sobre cabeçalhos e redirecionamentos ou quer reunir vários projetos em um servidor só."
        }
      }
    ]
  }
]
```
