Introdução: Por que migrar do Local para uma VPS?
Muitos desenvolvedores iniciantes e até experientes cometem o erro de manter seus projetos Node.js rodando em ambientes locais durante todo o ciclo de vida do desenvolvimento. O problema é que o ambiente local (localhost) é extremamente permissivo e diferente da realidade de um servidor Linux em produção. Ao tentar migrar sua aplicação para uma VPS (Virtual Private Server), você frequentemente se depara com erros de permissão, variáveis de ambiente não carregadas, processos morrendo silenciosamente e falhas na comunicação via HTTPS.
Este tutorial é dedicado a sysadmins, desenvolvedores backend e profissionais de TI que desejam automatizar e estruturar corretamente o processo de deploy de uma aplicação Node.js em um ambiente Linux (Ubuntu/Debian). Vamos sair do "funciona na minha máquina" para um ambiente robusto, seguro e escalável.
Abaixo, seguiremos um fluxo lógico: desde o provisionamento inicial do servidor até a configuração de um gerenciador de processos e proxy reverso com SSL gratuito.
Etapa 1: Preparação do Ambiente Local
Antes de tocar no servidor, sua aplicação local precisa estar pronta para produção. Isso significa garantir que não dependamos de módulos nativos que não foram instalados ou configurados corretamente, e que nossas variáveis de ambiente estejam separadas do código.
Primeiro, verifique se seu arquivo package.json possui as dependências de desenvolvimento separadas das de produção. Execute o comando abaixo na raiz do seu projeto local para garantir uma instalação limpa:
npm ci --production
Em seguida, crie um arquivo .env na raiz do projeto para armazenar segredos (como chaves de API, portas e senhas de banco de dados). Nunca envie este arquivo para o repositório Git.
# Exemplo de .env
NODE_ENV=production
PORT=3000
DB_HOST=seu-banco-dados.com
DB_USER=admin
DB_PASS=senha_forte
Instale a biblioteca dotenv se ainda não o fez, e garanta que ela seja carregada no início do seu arquivo principal (geralmente index.js ou app.js):
require('dotenv').config();
const express = require('express');
// ... resto do código
Etapa 2: Acesso e Atualização do Servidor Linux
Agora, conecte-se à sua VPS via SSH. Utilize o usuário root ou um usuário com privilégios de sudo. Se você está usando Ubuntu ou Debian (as distribuições mais comuns para hospedar Node.js), o primeiro passo é atualizar o sistema operacional para garantir que todos os pacotes estejam na versão mais recente e segura.
ssh user@seu-ip-da-vps
sudo apt update && sudo apt upgrade -y
O comando apt update atualiza a lista de pacotes disponíveis, e o upgrade instala as versões mais recentes. A flag -y confirma automaticamente as instalações, o que é útil em scripts de automação.
Etapa 3: Instalação do Node.js e NPM
Diferente da instalação local, onde você pode usar o nvm (Node Version Manager) para alternar entre versões facilmente, em produção é recomendável instalar o Node.js via gerenciador de pacotes do sistema ou através de binários pré-compilados estáveis. Para este tutorial, utilizaremos o método recomendado pela própria equipe do Node.js usando o repositório oficial.
Primeiro, instale as ferramentas necessárias para baixar e compilar módulos nativos se necessário:
sudo apt install -y curl gnupg
Agora, adicione o repositório do NodeSource (versão LTS é recomendada para produção) e instale o Node.js. Vamos usar a versão 20.x como exemplo:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
Verifique as instalações para garantir que tudo funcionou:
node --version
npm --version
Você deve ver a versão do Node.js e do npm instalados. Com isso, seu servidor Linux está preparado para executar JavaScript.
Etapa 4: Transferência dos Arquivos da Aplicação
Agora precisamos mover o código da sua máquina local para a VPS. Existem duas abordagens principais: usar Git (recomendado para projetos maiores) ou usar rsync (rápido para atualizações incrementais). Vamos focar na abordagem via Git, pois ela integra melhor com pipelines de CI/CD futuros.
No servidor, crie um diretório para a aplicação e clone o repositório:
sudo mkdir -p /var/www/meu-app
cd /var/www/meu-app
git clone https://github.com/seu-usuario/seu-repo.git .
Se você não quiser usar Git, pode usar o rsync da sua máquina local:
# Executado na MÁQUINA LOCAL
rsync -avz --exclude='node_modules' ./ user@seu-ip-da-vps:/var/www/meu-app/
A flag --exclude='node_modules' é crucial. Não envie a pasta node_modules. Ela deve ser instalada no servidor para garantir que os binários compatíveis com o Linux sejam baixados.
Etapa 5: Instalação de Dependências e Configuração do Banco de Dados
Conecte-se novamente ao servidor e navegue até a pasta do projeto:
cd /var/www/meu-app
Instale as dependências. Lembre-se de definir o ambiente como produção para evitar que dependências de teste sejam baixadas, economizando espaço e tempo:
export NODE_ENV=production
npm ci --omit=dev
Agora, copie o arquivo .env.example (ou crie um novo) para .env e preencha com as variáveis de ambiente corretas para o servidor. Você pode editar diretamente no servidor usando o editor nano:
nano .env
Insira os valores seguros, como senhas do banco de dados e chaves secretas. Salve (Ctrl+O, Enter) e saia (Ctrl+X).
Etapa 6: Gerenciamento de Processos com PM2
O maior erro de quem migra Node.js é iniciar a aplicação diretamente com node index.js. Se o processo cair ou o servidor reiniciar, sua aplicação ficará offline. Para resolver isso, utilizaremos o PM2, um gerenciador de processos para aplicações Node.js em produção.
Instale o PM2 globalmente:
sudo npm install -g pm2
Inicie sua aplicação com o PM2. O comando abaixo inicia a aplicação, monitora-a e garante que ela reinicie automaticamente em caso de falha:
pm2 start index.js --name "meu-app-node"
O --name é opcional, mas recomendado para facilitar a identificação se você hospedar múltiplas aplicações no mesmo servidor.
Para garantir que a aplicação inicie automaticamente quando o servidor VPS for reiniciado (boot), execute:
pm2 startup
pm2 save
O PM2 exibirá um comando de inicialização específico para seu sistema. Copie e cole esse comando no terminal. Isso configura o serviço systemd necessário para gerenciar o PM2.
Etapa 7: Configuração do Firewall (UFW)
Servidores Linux devem ter o firewall ativado por padrão. No Ubuntu, o UFW (Uncomplicated Firewall) é a ferramenta padrão. Vamos permitir apenas as portas essenciais.
Primeiro, verifique o status do UFW:
sudo ufw status
Se estiver desativado, ative-o. Mas antes, garanta que o SSH esteja permitido para não se bloquear fora do servidor:
sudo ufw allow OpenSSH
sudo ufw enable
Agora, precisamos decidir sobre a porta da aplicação. O PM2 pode rodar em qualquer porta (ex: 3000), mas o usuário root não deve expor portas baixas diretamente sem um proxy reverso. Vamos bloquear a porta 3000 inicialmente e usar o Nginx como proxy.
sudo ufw allow 'Nginx Full'
Se você estiver usando HTTP simples no momento, pode permitir temporariamente a porta da app para testar, mas lembre-se de bloqueá-la após configurar o Nginx:
# Apenas para teste inicial
sudo ufw allow 3000
Etapa 8: Proxy Reverso com Nginx
O Nginx atuará como um gateway, recebendo o tráfego externo na porta 80 (HTTP) ou 443 (HTTPS) e redirecionando para a porta onde seu Node.js está rodando internamente. Isso permite que você use subdomínios e configure SSL facilmente.
Instale o Nginx:
sudo apt install nginx -y
Crie um novo arquivo de configuração no diretório sites-available:
sudo nano /etc/nginx/sites-available/meu-app
Cole a seguinte configuração, substituindo seu-dominio.com pelo seu domínio real e ajustando o nome do arquivo se necessário:
server {
listen 80;
server_name seu-dominio.com www.seu-dominio.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Ative essa configuração criando um link simbólico para o diretório sites-enabled:
sudo ln -s /etc/nginx/sites-available/meu-app /etc/nginx/sites-enabled/
Teste a configuração do Nginx para evitar erros de sintaxe:
sudo nginx -t
Se o teste for bem-sucedido, recarregue o Nginx:
sudo systemctl reload nginx
Agora, atualize suas regras de firewall para bloquear a porta 3000 externamente, já que o acesso será feito via Nginx na porta 80:
sudo ufw delete allow 3000
Etapa 9: Segurança SSL com Let's Encrypt (Certbot)
Nenhum deploy moderno está completo sem HTTPS. Vamos instalar o Certbot para obter certificados SSL gratuitos do Let's Encrypt.
sudo apt install certbot python3-certbot-nginx -y
Execute o Certbot e selecione seu domínio nas opções interativas:
sudo certbot --nginx -d seu-dominio.com -d www.seu-dominio.com
O Certbot irá:
- Solicitar um email de contato.
- Pedir aceitação dos termos de serviço.
- Configurar automaticamente o Nginx para redirecionar HTTP para HTTPS.
- Instalar os certificados SSL.
O sistema avisará se deseja redirecionar todo o tráfego para HTTPS. Escolha a opção 2 (Redirecionar). Isso garante que todos os dados transmitidos sejam criptografados.
Etapa 10: Monitoramento e Logs
Com tudo configurado, é hora de verificar se a aplicação está rodando corretamente. Use o PM2 para visualizar o status:
pm2 list
Se houver algum erro no estado (como "erro" ou "stopped"), verifique os logs detalhados:
pm2 logs meu-app-node
Os logs do PM2 são extremamente úteis para depurar problemas de inicialização, erros de conexão com banco de dados ou variáveis de ambiente faltantes. Para acompanhar os logs em tempo real no terminal, use:
pm2 monit
Isso abrirá uma interface visual no terminal mostrando uso de CPU e memória.
Conclusão e Boas Práticas
Você acabou de migrar com sucesso sua aplicação Node.js do ambiente local para uma VPS Linux profissional. Este processo estabelece uma base sólida para escalar seus projetos. Lembre-se das seguintes práticas recomendadas:
- Backup Regular: Configure backups automáticos do banco de dados e do diretório
/var/www. - Atualizações Semanais: Execute
sudo apt update && sudo apt upgraderegularmente para manter o servidor seguro. - Monitoramento Contínuo: Considere integrar ferramentas como PM2 Plus ou serviços de monitoramento externo (como UptimeRobot) para alertas de indisponibilidade.
- Segurança de Chaves SSH: Desative a autenticação por senha no servidor e use apenas chaves SSH para acesso root/admin.
A migração não termina aqui. À medida que sua aplicação cresce, considere implementar pipelines de CI/CD (Integração Contínua/Entrega Contínua) usando GitHub Actions ou GitLab CI para automatizar essas etapas de deploy, tornando o processo ainda mais rápido e livre de erros humanos.
Agora é com você: teste a conexão em seu navegador, verifique se o cadeado de segurança aparece e celebre o novo estágio da sua infraestrutura! Se encontrou dificuldades em alguma etapa específica, revise os logs do Nginx (/var/log/nginx/error.log) ou do PM2 para identificar gargalos.