Como hospedar uma aplicação Node.js

Para hospedar uma aplicação Node.js, você precisa de um servidor que rode a versão certa do Node, do seu código com o package.json e de um comando de início. A porta e os segredos devem vir de variáveis de ambiente.

Atualizado em 6 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Preparar o projeto Node.js para rodar fora da sua máquina
  • Escrever um servidor que lê a porta do ambiente e encerra com segurança
  • Verificar o deploy e corrigir os erros mais comuns
Nesta página

Uma aplicação Node.js funciona na sua máquina porque ali estão o Node certo, as dependências instaladas e as variáveis que você configurou. Hospedar é reproduzir esse ambiente num servidor que fica ligado o tempo todo e que outras pessoas conseguem acessar.

O caminho é o mesmo para uma API, um site com servidor ou um bot: preparar o projeto, enviar o código, instalar as dependências e iniciar o processo. Este guia usa uma API com Express como exemplo, mas os passos valem para qualquer app Node.js. Para a visão geral do conceito, veja o que é deploy.

1Projeto localpackage.jsonpackage-lock.jsonindex.jsEnvio ao servidorsem node_modules e .env2npm ci --omit=devdependências do lockfile3Processo nodeescuta a porta de PORT4PORTvariável de ambiente
Envie o projeto com o lockfile, instale com npm ci e inicie o node na porta que o ambiente informa em PORT.

O que você precisa antes de hospedar?#

  • Uma versão do Node definida. Escolha uma versão LTS e use a mesma localmente e em produção.
  • Um package.json completo, com as dependências e um script de início.
  • Um package-lock.json commitado, para que a instalação seja idêntica em qualquer máquina.
  • Um lugar para rodar: uma VPS, um container ou uma plataforma de hospedagem. A diferença entre eles está em VPS vs plataforma de nuvem.

Qual LTS escolher? Para um projeto novo, use a versão LTS ativa do Node.js, desde que suas dependências a suportem, e declare a versão no package.json. O calendário oficial mostra qual versão está nessa fase e até quando cada uma recebe correções.

Como preparar o projeto?#

Crie a estrutura mínima:

bash
mkdir minha-api && cd minha-api
npm init -y
npm install express

Ajuste o package.json para módulos ES, com versão do Node e scripts:

json
{
  "name": "minha-api",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "engines": { "node": ">=24" },
  "scripts": {
    "start": "node index.js",
    "dev": "node --watch --env-file-if-exists=.env index.js"
  },
  "dependencies": {
    "express": "^5.0.0"
  }
}

O campo engines documenta a versão esperada, e o script start é o comando que o servidor vai executar. O dev usa duas flags nativas do Node: --watch reinicia o processo quando um arquivo muda, e --env-file-if-exists carrega as variáveis de um arquivo .env (sem erro se ele não existir), sem precisar do pacote dotenv.

Como escrever um servidor pronto para produção?#

Um servidor de testes vira um servidor de produção quando lê a porta do ambiente, mantém os segredos fora do código e trata o sinal de encerramento.

js
// index.js
import express from "express";

const app = express();
const port = Number(process.env.PORT) || 3000;

app.get("/", (req, res) => {
  res.send("Olá, mundo!");
});

app.get("/health", (req, res) => {
  res.json({ status: "ok" });
});

const server = app.listen(port, "0.0.0.0", () => {
  console.log(`Servidor ouvindo na porta ${port}`);
});

// Ao receber SIGTERM (reinício ou deploy), para de aceitar
// conexões novas e termina as que estão em andamento.
process.on("SIGTERM", () => {
  server.close(() => process.exit(0));
});

Por que cada parte importa:

  • process.env.PORT: a plataforma ou o servidor decide a porta e informa por variável. Fixar 3000 funciona só na sua máquina. O || 3000 é o valor para desenvolvimento.
  • Rota /health: dá a você (e a monitores externos) um endereço leve para testar se o app responde.
  • SIGTERM: é o sinal que o sistema envia para pedir que o processo termine. Quando você registra um ouvinte, o Node deixa de sair na hora (o comportamento padrão), então você precisa encerrar o processo explicitamente, como no exemplo.

Teste local com npm run dev e abra http://localhost:3000/health.

Como lidar com variáveis de ambiente e segredos?#

Tokens, senhas de banco e chaves de API ficam em variáveis de ambiente, nunca no repositório. Leia cada uma com process.env.NOME. Localmente, use um arquivo .env e coloque-o no .gitignore; em produção, cadastre cada variável no painel do seu provedor ou no processo do servidor. O guia o que são variáveis de ambiente detalha o padrão.

Falhe cedo quando faltar uma variável obrigatória. Assim, em vez de um erro obscuro mais adiante, você recebe uma mensagem clara na inicialização:

js
if (!process.env.DATABASE_URL) {
  throw new Error("DATABASE_URL não definida");
}

Como enviar o código e iniciar o processo?#

O fluxo geral, em qualquer hospedagem:

  1. Envie o código sem node_modules e sem o .env (use um .gitignore).
  2. No servidor, instale as dependências exatas do lockfile: npm ci --omit=dev.
  3. Defina as variáveis de ambiente, incluindo NODE_ENV=production.
  4. Inicie com npm start (ou node index.js).
  5. Mantenha o processo vivo: em uma VPS, com um supervisor como o systemd ou o PM2; em containers e plataformas, com a política de reinício delas. Veja também como empacotar com Docker.

Se o seu app é uma API, revise o checklist de produção para APIs antes de abrir para o público.

Como verificar se deu certo?#

Depois do deploy, confirme em três passos:

  1. Logs: a linha "Servidor ouvindo na porta" deve aparecer sem erros em seguida.
  2. Requisição: chame a rota /health pelo endereço público e espere {"status":"ok"}.
  3. Reinício: reinicie o app e confirme que ele volta sozinho.

Quais erros são mais comuns?#

  • Error: listen EADDRINUSE: address already in use: a porta já está ocupada por outro processo. Pare a instância antiga ou mude a porta.
  • Cannot find module 'express': as dependências não foram instaladas, ou o pacote está em devDependencies e você instalou com --omit=dev. Mova para dependencies.
  • SyntaxError: Cannot use import statement outside a module: falta "type": "module" no package.json, ou você usa import em arquivo tratado como CommonJS.
  • App sobe, mas o site não abre: o servidor escuta numa porta fixa em vez de process.env.PORT, ou só em localhost. Em containers, escute em 0.0.0.0.
  • Funciona local, cai em produção: versão do Node diferente, variável de ambiente ausente ou memória insuficiente. Compare o que mudou entre os ambientes.

Como fazer isso na Square Cloud#

O fluxo deste guia muda pouco na Square Cloud. Você envia o projeto por ZIP no painel, pela CLI, pelo GitHub (um push faz o deploy) ou pela extensão do VS Code, e o formulário de deploy detecta o index.js como arquivo principal. O arquivo squarecloud.app é opcional: o painel o gera no deploy. Se preferir o script do package.json, o campo de comando de início aceita qualquer comando de shell, como npm start ou npm run migrate && npm start.

A instalação segue duas regras que explicam erros da lista acima. A plataforma só roda npm install quando não existe node_modules, então envie o projeto sem essa pasta. E ela instala com NODE_ENV=production: o que estiver em devDependencies fica de fora, e o resultado é o Cannot find module. Não há etapa de build; para compilar, use um CI externo, como o GitHub Actions, ou coloque o build no comando de início. O runtime de TypeScript executa o seu código sem compilação prévia.

A porta vem da variável PORT, que a plataforma define, e o servidor escuta em 0.0.0.0, como no exemplo. As variáveis de ambiente ficam por aplicação no painel (que importa um .env), já existem durante a instalação e valem no próximo restart, sem rebuild. O container fica sempre ligado, e o reinício automático, ligado por padrão no deploy pelo painel, traz de volta um processo que encerrou com erro, então o PM2 é dispensável. Um estouro de memória para a aplicação até você aumentar a RAM. A saída do npm install e a linha "Servidor ouvindo na porta" aparecem nos logs em tempo real.

Cada aplicação web usa no mínimo 512 MB da RAM do plano, e o Hobby começa em R$ 12,49 por mês com 1 GB. O Node.js é um entre diversos runtimes, ao lado de Python, Go e Java: veja os runtimes disponíveis hoje em Runtimes e os planos em hospedagem de APIs.

Hospedagem de APIs

APIs em containers sempre ligados, sem cold start

Saiba mais

Perguntas frequentes

Qual versão do Node.js devo usar em produção?

Use a versão LTS ativa do Node.js, que recebe correções de segurança por mais tempo. Confira no calendário oficial do Node.js qual é ela antes de fixar a versão no projeto.

Preciso do PM2 para manter a aplicação no ar?

Depende do ambiente. Num servidor que você administra, um supervisor de processos reinicia o app se ele cair. Em plataformas que já reiniciam o processo sozinhas, o PM2 costuma ser desnecessário.

Preciso enviar a pasta node_modules?

Normalmente não. Envie o package.json e o package-lock.json e deixe o ambiente instalar as dependências com npm ci. A pasta node_modules pode ser enorme e depende do sistema operacional.

Posso hospedar uma aplicação Node.js escrita em TypeScript?

Sim. Você pode compilar para JavaScript antes do deploy ou usar uma plataforma que execute TypeScript diretamente. Rodar o código compilado costuma ser a opção mais previsível.

Próximo artigoComo hospedar FastAPI, Flask ou DjangoPara hospedar FastAPI, Flask ou Django, rode a aplicação com um servidor de produção (Uvicorn ou Gunicorn) em 0.0.0.0. Veja comandos, ajustes do Django e erros.