Nginx como proxy reverso na VPS

Nginx como proxy reverso é a arquitetura padrão para servir aplicações na VPS, ele recebe as requisições HTTP/HTTPS, roteia para o processo da aplicação (Node.js, Python, etc.) e devolve a resposta ao cliente. Isola a aplicação da internet, centraliza SSL e permite hospedar múltiplos serviços no mesmo servidor.

Instalar e estruturar o Nginx

Use o repositório oficial do Nginx para ter a versão mais recente:

bash
# Instalar Nginx do repositório oficial
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list

sudo apt update && sudo apt install -y nginx

# Verificar versão
nginx -v
sudo systemctl enable nginx

# Estrutura de diretórios:
# /etc/nginx/nginx.conf         — config principal
# /etc/nginx/conf.d/            — configs adicionais (carregadas automaticamente)
# /etc/nginx/sites-available/   — configs de sites (estilo Debian)
# /etc/nginx/sites-enabled/     — symlinks para sites ativos
# /var/log/nginx/access.log     — log de acesso
# /var/log/nginx/error.log      — log de erros

# Testar configuração antes de recarregar:
sudo nginx -t

# Recarregar sem downtime:
sudo nginx -s reload

Configuração de proxy reverso para Node.js

Arquivo de configuração completo para rotear tráfego para uma aplicação Node.js:

nginx
# /etc/nginx/conf.d/minha-api.conf

upstream minha_api {
    server 127.0.0.1:3000;
    keepalive 64;            # reutilizar conexões TCP com o backend
}

server {
    listen 80;
    server_name api.seudominio.com.br;

    # Tamanho máximo do corpo da requisição
    client_max_body_size 50M;

    # Timeouts
    proxy_connect_timeout 60s;
    proxy_send_timeout    60s;
    proxy_read_timeout    60s;

    location / {
        proxy_pass http://minha_api;
        proxy_http_version 1.1;

        # Headers essenciais para o backend
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Connection        "";   # necessário para keepalive

        # Não cachear respostas da API por padrão
        proxy_buffering off;
    }

    location /health {
        proxy_pass http://minha_api;
        access_log off;          # não logar health checks
    }
}

Múltiplos serviços no mesmo servidor

Hospedar diferentes aplicações em subdomínios distintos:

nginx
# /etc/nginx/conf.d/api.conf
server {
    listen 80;
    server_name api.seudominio.com.br;
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# /etc/nginx/conf.d/app.conf
server {
    listen 80;
    server_name app.seudominio.com.br;
    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# /etc/nginx/conf.d/admin.conf
server {
    listen 80;
    server_name admin.seudominio.com.br;

    # Restringir acesso por IP (painel admin)
    allow 177.10.0.1;     # IP do escritório
    deny all;

    location / {
        proxy_pass http://127.0.0.1:3002;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Roteamento por path em um único domínio

Direcionar diferentes caminhos para diferentes backends no mesmo domínio:

nginx
# /etc/nginx/conf.d/monolito-para-microservicos.conf
server {
    listen 80;
    server_name seudominio.com.br;

    # Frontend (Next.js / React)
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # API REST
    location /api/ {
        proxy_pass http://127.0.0.1:4000/;   # / no final: remove /api do path
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Serviço de upload de arquivos
    location /upload/ {
        proxy_pass http://127.0.0.1:5000/;
        client_max_body_size 200M;
        proxy_read_timeout 300s;
    }

    # Documentação estática
    location /docs/ {
        root /var/www;
        try_files $uri $uri/ =404;
    }
}

Redirecionar HTTP para HTTPS e www para não-www

Configurar redirecionamentos permanentes:

nginx
# Redirecionar HTTP → HTTPS
server {
    listen 80;
    server_name seudominio.com.br www.seudominio.com.br;
    return 301 https://seudominio.com.br$request_uri;
}

# Redirecionar www → sem www (em HTTPS)
server {
    listen 443 ssl;
    server_name www.seudominio.com.br;
    ssl_certificate     /etc/letsencrypt/live/seudominio.com.br/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/seudominio.com.br/privkey.pem;
    return 301 https://seudominio.com.br$request_uri;
}

# Servidor principal
server {
    listen 443 ssl;
    server_name seudominio.com.br;
    ssl_certificate     /etc/letsencrypt/live/seudominio.com.br/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/seudominio.com.br/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Host $host;
    }
}

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Vantagens do proxy reverso: SSL centralizado (um lugar para gerenciar certificados), múltiplos serviços em um IP, cache de arquivos estáticos, rate limiting, proteção contra ataques comuns (buffer overflow, slow HTTP), logs centralizados e reload sem downtime. Aplicações Node.js/Python não devem ficar expostas diretamente na internet.

nginx -s reload: carrega nova configuração sem downtime, o processo master relê o config e os workers antigos terminam gracefully enquanto novos são iniciados. systemctl restart: para completamente e reinicia, causa downtime. Use reload para mudanças de config em produção. Use restart apenas para atualizações do binário do Nginx.

Na aplicação Node.js: console.log(req.headers["x-real-ip"]). Se estiver vendo 127.0.0.1 em vez do IP do cliente, certifique-se que proxy_set_header X-Real-IP $remote_addr está no Nginx. Em Express: app.set("trust proxy", 1) para que req.ip use X-Forwarded-For corretamente.

Sem keepalive: Nginx abre nova conexão TCP para cada requisição ao backend, caro em latência e recursos. Com keepalive 64: mantém até 64 conexões TCP persistentes abertas com o backend, reutilizando-as para múltiplas requisições. Para APIs com alto throughput: keepalive pode reduzir latência em 10-50ms por requisição.

Nginx é extremamente eficiente, usa arquitetura event-driven assíncrona. Um processo master + 4 workers consome ~30-50 MB de RAM total. Pode atender milhares de conexões simultâneas com esse consumo. Contrast com Apache em modo prefork: cada requisição exige um processo dedicado (~10-30 MB por processo).