# Setup Node Produção: Guia Completo Passo a Passo

> Node.js em produção exige configuração além do comando node server.js. O guia completo cobre variáveis de ambiente, logging estruturado, health checks e graceful shutdown para estabilidade e segurança. A implementação desses elementos garante um servidor resiliente a falhas e monitorável em ambientes reais. O processo passo a passo permite aplicar práticas profissionais de deploy diretamente no código.

*Digitorack · Apps e Software · 09 de setembro de 2026 · Letícia Sampaio Khoury*

Colocar uma aplicação Node.js em produção vai além de rodar node server.js. Neste guia, você vai configurar variáveis de ambiente, logging estruturado, health checks e graceful shutdown para um servidor estável e seguro.

Colocar uma aplicação Node.js em produção é mais do que digitar node server.js e torcer para funcionar. No uso real, o que separa um servidor que aguenta o tranco de um que cai no meio da madrugada são decisões de configuração que você toma antes do deploy. Este guia cobre o caminho completo, do ambiente à segurança, com passos que você pode aplicar hoje mesmo em um servidor Ubuntu.

Se você já tem experiência com Node em desenvolvimento, mas sente que falta um roteiro claro para o ambiente de produção, este guia é para você. Ao final, você terá um servidor com variáveis de ambiente organizadas, logs que ajudam de verdade, health checks funcionando e um desligamento gracioso que não derruba requisições em andamento.

## Pré-requisitos

Antes de começar, confirme que você tem acesso a um servidor Linux (Ubuntu é o mais comum), com Node.js instalado (versão 18 ou superior é o ideal) e um usuário com privilégios sudo. Você também precisa do código da sua aplicação em um repositório Git. Sem isso, os passos abaixo não fazem sentido.

## Passo 1: Configure as variáveis de ambiente

Nada de chave de API ou string de conexão hardcoded no código. Em produção, essas informações vivem em um arquivo .env fora do repositório. Crie o arquivo na raiz do projeto na máquina servidora e preencha com os valores reais. Use a biblioteca dotenv para carregar essas variáveis no início da aplicação.

require('dotenv').config();

const dbUrl = process.env.DATABASE_URL; const apiKey = process.env.API_KEY;

**Erro comum a evitar:** versionar o arquivo .env no Git. Adicione .env ao seu .gitignore desde o primeiro commit. Uma variável vazada é uma porta aberta para problemas sérios.

**Dica:** crie um arquivo .env.example no repositório com as chaves e valores fictícios. Assim, outro desenvolvedor do time sabe exatamente quais variáveis precisa configurar.

## Passo 2: Use um processo manager (PM2)

Rodar o Node diretamente no terminal é frágil. Se o processo cair, ninguém reinicia. O PM2 resolve isso: ele mantém sua aplicação viva, reinicia após falhas e ainda guarda os logs em arquivos.

Instale o PM2 globalmente e inicie sua aplicação com ele:

npm install -g pm2 pm2 start server.js --name minha-api pm2 save

O comando pm2 save salva a lista de processos para que o PM2 os restaure após uma reinicialização do servidor. Para garantir que o PM2 inicie junto com o sistema, rode pm2 startup e siga a instrução que ele exibir.

**Erro comum a evitar:** esquecer de rodar pm2 startup. Sem isso, após um reboot do servidor, sua aplicação fica fora do ar até você subir manualmente.

**Dica:** use pm2 monit para acompanhar CPU e memória da sua aplicação em tempo real. Isso ajuda a perceber vazamentos antes que eles derrubem o servidor.

## Passo 3: Configure o logging estruturado

Console.log serve para desenvolvimento. Em produção, você precisa de logs que possam ser filtrados e analisados. Logging estruturado significa emitir cada entrada como JSON, com timestamp, nível e contexto.

Use a biblioteca pino, que é rápida e produz JSON por padrão:

const pino = require('pino'); const logger = pino({ level: process.env.LOG_LEVEL || 'info' });

logger.info({ userId: 123 }, 'usuário autenticado');

**Erro comum a evitar:** logar dados sensíveis, como senhas ou tokens completos. Um log que vaza um token de acesso é um incidente de segurança. Se precisar logar um token, trunque ele.

**Dica:** defina o nível de log via variável de ambiente. Em produção, info é um bom padrão. Em debugging, você pode subir para debug sem alterar o código.

## Passo 4: Implemente health checks

Um health check é um endpoint que informa se sua aplicação está viva e pronta para receber tráfego. Load balancers e orquestradores usam isso para decidir se enviam requisições para o seu servidor.

Crie uma rota /health que retorna status 200 e um JSON simples quando tudo está bem:

app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', uptime: process.uptime() }); });

**Erro comum a evitar:** health check que só verifica se o processo está de pé. O ideal é que ele também confirme se as dependências críticas, como banco de dados, estão acessíveis. Um health check superficial esconde problemas reais.

**Dica:** coloque o health check em uma rota separada, sem autenticação, para que o load balancer consiga acessar sem fricção. Mas não exponha informações internas nesse endpoint.

## Passo 5: Implemente graceful shutdown

Quando o servidor recebe um sinal de encerramento (SIGTERM), ele deve parar de aceitar novas conexões, terminar as requisições em andamento e só então fechar as conexões com banco e serviços externos. Sem isso, você corre o risco de corromper dados ou deixar usuários com requisições pela metade.

No seu código, adicione um handler para o sinal:

process.on('SIGTERM', () => { logger.info('Sinal SIGTERM recebido, encerrando graciosamente'); server.close(() => { // fechar conexões com banco aqui process.exit(0); }); });

**Erro comum a evitar:** chamar process.exit() imediatamente no handler, sem esperar o servidor fechar. Isso derruba requisições em andamento. Dê um tempo limite razoável (30 segundos é comum) e force a saída se o servidor não fechar sozinho.

**Dica:** teste o graceful shutdown localmente. Envie um SIGTERM para o processo com kill -15 e observe se as requisições em andamento são concluídas antes da saída.

## Passo 6: Segurança básica

Segurança não é um passo único, é uma camada que se constrói. No mínimo, faça o seguinte: rode sua aplicação com um usuário sem privilégios de root, nunca use a porta 80 diretamente (use um reverse proxy como Nginx na frente), e mantenha as dependências atualizadas.

Atualize as dependências regularmente com npm audit para identificar vulnerabilidades conhecidas. Configure um firewall para permitir apenas as portas necessárias (geralmente 80 e 443, além da porta SSH).

**Erro comum a evitar:** rodar a aplicação como root. Se sua aplicação for comprometida, o atacante ganha acesso total ao servidor. Crie um usuário dedicado, como nodeapp, e execute o PM2 com ele.

**Dica:** use o Nginx como proxy reverso. Ele lida com SSL, compressão e headers de segurança, além de servir arquivos estáticos com mais eficiência que o Node.

## Checklist final: o que você configurou

- Variáveis de ambiente em arquivo .env fora do Git
- Processo gerenciado pelo PM2 com reinício automático
- Logs estruturados em JSON com níveis definidos
- Endpoint /health funcional e verificando dependências
- Graceful shutdown tratando SIGTERM corretamente
- Aplicação rodando com usuário sem privilégios e atrás de um proxy reverso

Se você completou todos os passos, seu ambiente Node.js em produção está mais sólido que a maioria dos servidores por aí. O próximo passo natural é configurar um pipeline de deploy automatizado com CI/CD, mas isso já é assunto para outro guia.

## FAQ

### Por que não devo rodar o Node.js diretamente na porta 80?

A porta 80 exige privilégios de root, o que significa rodar sua aplicação com um usuário administrativo. Isso aumenta o risco de segurança. Além disso, o Node não é otimizado para servir arquivos estáticos ou lidar com SSL. Um reverse proxy como Nginx resolve esses pontos e ainda distribui melhor o tráfego.

### Qual a diferença entre desenvolvimento e produção no Node.js?

Em desenvolvimento, você prioriza recarga rápida e logs verbosos. Em produção, você prioriza estabilidade, segurança e observabilidade. Isso significa usar processo manager, logging estruturado, variáveis de ambiente protegidas e health checks. A variável NODE_ENV também muda o comportamento de algumas bibliotecas, deixando-as mais rápidas em produção.

### Como faço para atualizar minha aplicação sem derrubar o servidor?

O PM2 oferece o comando pm2 reload que reinicia sua aplicação sem downtime, desde que você tenha mais de um processo rodando em modo cluster. Ele faz um rolling restart, ou seja, reinicia um processo por vez enquanto os outros continuam atendendo requisições. Combine isso com o graceful shutdown para uma troca de versão quase invisível.

### O que é um health check e por que preciso dele?

Um health check é um endpoint HTTP que informa se sua aplicação está saudável e pronta para receber tráfego. Load balancers e serviços de orquestração usam essa resposta para decidir se enviam requisições para o seu servidor ou se o consideram fora de serviço. Sem ele, o tráfego pode continuar indo para uma instância quebrada.

### Preciso usar Docker para colocar Node em produção?

Docker é uma opção, não uma obrigação. Ele ajuda a padronizar o ambiente e facilitar o deploy em diferentes servidores, mas adiciona complexidade. Se você tem um servidor único e um processo simples, PM2 direto no sistema operacional resolve bem. Avalie se a portabilidade e o isolamento do Docker valem o esforço extra para o seu caso.

---

Fonte (canonical): https://digitorack.com.br/apps-e-software/setup-node-producao-guia-completo-passo-a-passo/
