CI/CD do Zero: Automatize Deploy no Servidor Linux com GitHub Actions
CI/CD (Continuous Integration / Continuous Delivery) é a prática de automatizar a validação e entrega de código. Em vez de deploys manuais e arriscados, cada push no repositório dispara uma sequência de etapas automáticas que testam, empacotam e entregam o código em produção.
- CI (Integração Contínua): todo commit é testado automaticamente antes de entrar na branch principal
- CD (Entrega Contínua): o que passou nos testes vai para produção sem intervenção manual
GitHub Actions
GitHub Actions é a ferramenta de CI/CD integrada ao GitHub. É gratuita para repositórios públicos e tem 2.000 minutos/mês para repositórios privados no plano free.
Um workflow é definido em arquivos YAML dentro de .github/workflows/. Ele define quando rodar (gatilho), onde rodar (runner) e o que fazer (jobs/steps).
Estrutura do Workflow
# .github/workflows/ci.yml
name: CI — Testa a cada push
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest # runner: VM Ubuntu limpa
steps:
- name: Baixar o código
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Instalar dependências
run: npm ci
- name: Rodar testes
run: npm test
- name: Verificar lint
run: npm run lint
Deploy Automático via SSH
Depois de testar, o segundo job faz o deploy no servidor Linux:
# .github/workflows/deploy.yml
name: CI/CD — Testa e faz deploy
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
deploy:
needs: test # só roda se test passar
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ec2-user
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /home/plataforma
git pull origin main
npm install --production
pm2 restart app || pm2 start server.js --name app
Configurando Secrets
Nunca coloque senhas, chaves ou IPs diretamente no YAML. Use os Secrets do GitHub:
Settings → Secrets and variables → Actions → New repository secret
SERVER_HOST = 54.123.45.67
SSH_PRIVATE_KEY = (conteúdo da sua chave privada .pem)
Os secrets ficam disponíveis via ${{ secrets.NOME }} e nunca aparecem nos logs.
Pipeline com Docker
Para aplicações containerizadas, o pipeline faz build, push da imagem e atualiza o container em produção:
name: Build e Deploy Docker
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login no Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build e push da imagem
run: |
IMAGE=${{ secrets.DOCKER_USER }}/minha-app
docker build -t $IMAGE:${{ github.sha }} -t $IMAGE:latest .
docker push $IMAGE:${{ github.sha }}
docker push $IMAGE:latest
- name: Deploy no servidor
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ec2-user
key: ${{ secrets.SSH_PRIVATE_KEY }}
envs: DOCKER_USER,GITHUB_SHA
script: |
docker pull $DOCKER_USER/minha-app:$GITHUB_SHA
docker stop minha-app || true
docker rm minha-app || true
docker run -d --name minha-app --restart unless-stopped -p 80:3000 $DOCKER_USER/minha-app:$GITHUB_SHA
env:
DOCKER_USER: ${{ secrets.DOCKER_USER }}
GITHUB_SHA: ${{ github.sha }}
Conceitos Importantes
- Jobs: etapas independentes (ou dependentes com
needs:). Cada job roda em sua própria VM limpa. - Steps: comandos dentro de um job, executados em sequência.
- Actions: blocos reutilizáveis da comunidade (como
actions/checkout,appleboy/ssh-action). - Matrix: roda o mesmo job em múltiplas versões (Node 18, 20, 22 em paralelo).
- Artifacts: arquivos passados entre jobs (ex: binário compilado no build, consumido no deploy).
CI/CD para Sysadmins
Mesmo sem ser desenvolvedor, sysadmins se beneficiam diretamente de pipelines:
- Deploy de configurações Ansible a cada push no repositório de infra
- Regeneração automática de sitemap ou arquivos estáticos após merge
- Testes de conectividade e lint de Terraform antes de aplicar mudanças em produção
- Notificação no Slack quando um deploy falha
Entender CI/CD é hoje um requisito para qualquer posição de sysadmin pleno em diante — a diferença entre quem "gerencia servidor" e quem "entrega infraestrutura".