A automação de processos de desenvolvimento e infraestrutura é um pilar fundamental para equipes modernas que buscam agilidade, consistência e redução de erros humanos. Neste tutorial, vamos construir uma pipeline de CI/CD (Integração Contínua e Entrega Contínua) completa para uma aplicação Node.js, levando o código do seu ambiente local diretamente para uma VPS (Virtual Private Server) em Linux.
O objetivo é simples: ao fazer um push para o repositório Git, o servidor automaticamente baixa as últimas alterações, instala dependências e reinicia a aplicação sem necessidade de intervenção manual. Vamos utilizar ferramentas leves e amplamente adotadas pela comunidade, focando na praticidade da configuração via SSH e scripts shell.
Pré-requisitos e Preparação do Ambiente
Antes de começarmos a configurar o pipeline, é essencial garantir que o ambiente esteja preparado. Você precisará ter acesso root ou um usuário com privilégios sudo na sua VPS, bem como uma conta em um serviço de hospedagem de código, como GitHub, GitLab ou Bitbucket.
Primeiro, atualize o sistema operacional da sua VPS para garantir que todas as bibliotecas estejam seguras e atualizadas. Conecte-se ao seu servidor via terminal:
sudo apt update && sudo apt upgrade -y
Agora, vamos instalar o Node.js e o Yarn (ou npm). Para este tutorial, utilizaremos o Node Version Manager (nvm) para garantir flexibilidade na versão do Node.js, mas a instalação via package manager também é válida.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
source ~/.bashrc
nvm install --lts
Verifique se a instalação foi bem-sucedida:
node -v
npm -v
Criando a Aplicação de Exemplo
Se você já possui uma aplicação Node.js, pule esta etapa. Caso contrário, vamos criar uma estrutura básica para testar o pipeline. No seu computador local, crie um diretório e inicialize o projeto:
mkdir meu-app-node && cd meu-app-node
npm init -y
Instale o framework Express.js como dependência:
npm install express
Crie um arquivo index.js com o seguinte conteúdo:
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Deploy automatizado com sucesso!');
});
app.listen(port, () => {
console.log(`Servidor rodando na porta ${port}`);
});
Defina o script de início no seu package.json. Edite o arquivo e adicione a linha "start":
"scripts": {
"start": "node index.js"
}
Inicialize um repositório Git, faça o commit inicial e envie para sua plataforma remota (GitHub/GitLab):
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://seu-repositorio.git
git push -u origin main
Configurando a VPS para Receber Deploy
Agora que o código está no repositório, precisamos preparar o servidor Linux para receber e executar essas mudanças. A estratégia aqui será usar um script shell simples que atuará como um "webhook manual" ou pode ser integrado com gatilhos do Git.
Crie um diretório específico para sua aplicação na VPS:
sudo mkdir -p /var/www/meu-app
sudo chown -R $USER:$USER /var/www/meu-app
Navegue até esse diretório e clone o repositório pela primeira vez manualmente:
cd /var/www/meu-app
git clone https://seu-repositorio.git .
Instale as dependências do Node.js no servidor. Isso é crucial, pois o ambiente da VPS não herga as dependências do seu computador local:
npm install --production
Criando o Script de Deploy
O coração do nosso pipeline é um script shell que irá: 1) Puxar as últimas mudanças do Git, 2) Instalar dependências (caso haja alterações no package.json), e 3) Reiniciar a aplicação. Vamos usar o PM2 como gerenciador de processos para garantir que a aplicação fique em segundo plano e reinicie automaticamente em caso de falhas.
Instale o PM2 globalmente:
npm install -g pm2
Inicie a aplicação com o PM2 pela primeira vez para gerar a configuração:
pm2 start index.js --name "meu-app"
Agora, crie um script de deploy. Vamos chamá-lo de deploy.sh. Crie este arquivo no diretório raiz do seu projeto local (ou na VPS, se preferir gerenciar via SSH):
#!/bin/bash
cd /var/www/meu-app || exit
echo "Iniciando deploy..."
# 1. Pull das últimas alterações
git pull origin main
# 2. Instalar dependências apenas se houver mudanças
if [ -f "package-lock.json" ]; then
npm ci --production
fi
# 3. Reiniciar o serviço com PM2
pm2 restart meu-app
echo "Deploy finalizado com sucesso!"
Dê permissão de execução ao script:
chmod +x deploy.sh
Automatizando via Webhook do GitHub (GitHub Actions)
Para tornar o processo verdadeiramente automatizado, vamos utilizar o GitHub Actions. Esta ferramenta permite executar scripts sempre que houver um evento no seu repositório, como um push para a branch principal.
No seu projeto local, crie o seguinte caminho de diretórios: .github/workflows/deploy.yml.
Dentro desse arquivo, definiremos o workflow. A lógica será: quando houver um push para main, o script deploy.sh na VPS será executado via SSH.
name: Deploy Node.js para VPS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/meu-app
git pull origin main
npm ci --production
pm2 restart meu-app
Para que isso funcione, você precisa configurar as credenciais de acesso na VPS como segredos no repositório do GitHub:
- Vá em Settings > Secrets and variables > Actions.
- Crie o segredo
HOSTcom o IP público da sua VPS. - Crie o segredo
USERNAMEcom seu nome de usuário na VPS (ex:ubuntuouroot). - Crie o segredo
SSH_KEY. Para obter isso, rode no seu computador local:cat ~/.ssh/id_rsae copie o conteúdo. Não compartilhe essa chave com ninguém.
Com essas variáveis configuradas, qualquer commit enviado para a branch main acionará o pipeline. O GitHub Actions se conectará à sua VPS, executará os comandos de pull e reinício, e retornará o status do build.
Melhorias de Segurança e Boas Práticas
A automação é poderosa, mas requer cuidado com segurança. Usar chaves SSH privadas diretamente em workflows pode ser arriscado se o repositório for público. Uma abordagem mais robusta para ambientes de produção envolve o uso de tokens de acesso pessoal (PAT) ou chaves de deploy específicas.
Além disso, considere os seguintes pontos para refinar sua infraestrutura:
- Rollback Automático: Se o deploy falhar (ex: erros de sintaxe no código), você deseja reverter para a versão anterior? O PM2 suporta versionamento. Você pode configurar o script para verificar o status do
npm starte chamarpm2 restart meu-app --update-envou até mesmopm2 resetse necessário. - Variáveis de Ambiente: Nunca hardcode credenciales de banco de dados ou chaves de API no código. Utilize o PM2 para gerenciar variáveis de ambiente através do arquivo
ecosystem.config.js. Isso permite que você definaENV: productione carregar um arquivo.envespecífico para a VPS. - Logs: Monitore os logs da aplicação. Com o PM2, você pode rodar
pm2 logs meu-apppara ver o output em tempo real. Para produção, considere integrar com ferramentas como ELK Stack ou simples rotação de logs para não lotar o disco da VPS. - Firewall: Certifique-se de que sua VPS tenha o firewall configurado (ex: UFW ou Firewall da Cloud Provider) bloqueando portas desnecessárias. A porta 3000 (ou a que seu app usa) deve estar aberta, mas a porta SSH também precisa estar segura.
Testando o Pipeline
Agora vem a parte divertida: ver a mágica acontecer. Faça uma pequena alteração no seu arquivo index.js local:
app.get('/', (req, res) => {
res.send('Deploy automatizado atualizado!');
});
Faça o commit e o push:
git add .
git commit -m "Atualiza mensagem de boas-vindas"
git push origin main
Imediatamente, você verá a ação do GitHub ser acionada. Acompanhe o progresso na aba Actions do seu repositório. Se tudo correr bem, a pipeline passará pelo status verde.
Volte ao terminal da sua VPS e verifique se a aplicação está respondendo com a nova mensagem:
curl localhost:3000
O resultado deve ser Deploy automatizado atualizado!. Se você alterar o código novamente, o ciclo se repete. Isso é integração contínua e entrega contínua em ação.
Conclusão
A configuração de um pipeline CI/CD para Node.js em uma VPS Linux não precisa ser complexa ou exigir ferramentas pesadas como Kubernetes no início. Com scripts shell simples, o PM2 para gerenciamento de processos e GitHub Actions para orquestração, você cria um fluxo profissional, rápido e confiável.
Este setup escala bem: conforme sua aplicação cresce, você pode adicionar etapas de testes unitários (Jest/Mocha), linting (ESLint) e até mesmo construção de imagens Docker antes do deploy. No entanto, a base estabelecida aqui — automatizar o pull e o reinício dos serviços — é o primeiro passo fundamental para qualquer profissional de TI que deseja entregar valor ao usuário final com mais velocidade e segurança.
Lembre-se sempre de testar alterações em um ambiente de staging antes de aplicar na produção, mesmo com automação. A confiança no seu pipeline cresce a cada deploy bem-sucedido e monitorado.