sistema-de-chamados/docs/migracao-sistema-2025-11-15.md

8.1 KiB
Raw Permalink Blame History

Migração do stack sistema para a VPS 154.12.253.40 (15/11/2025)

Este documento registra o procedimento completo usado para clonar e mover o stack sistema (Convex self-hosted + dashboard + web/Next.js) da VPS antiga 217.216.64.168 para a VPS nova 154.12.253.40 (ambas Ubuntu 24.04 com Docker Swarm). Use-o como referência para futuros blue/green ou rollbacks.

1. Componentes inventariados

Item VPS antiga VPS nova
Hostname vmi2889318 vmi2872619
CPU/RAM 4 vCPU / 8GB 8 vCPU / 24GB
Stack sistema_convex_backend, sistema_convex_dashboard, sistema_web os mesmos + outros stacks existentes
Redes relevantes traefik_public, digital_network idem
Volumes do stack sistema_convex_data, sistema_sistema_db, sistema_db copiados 1:1
Bind mount /apps/sistema (5GB) /home/renan/apps/sistema + symlink /apps/sistema

Arquivos auxiliares recuperados da VPS antiga e copiados para /root na nova:

  • /root/services.json inventário completo de serviços, útil para recriar stacks.
  • /root/replay_services_from_json.sh script que recria serviços usando services.json.

2. Pré-requisitos e boas práticas

  1. Autenticação: senha root na VPS antiga (sshpass) e chave codex_ed25519 para a nova (chmod 600).
  2. Congelamento de escrita: antes do delta final, escalar a 0 os serviços que escrevem (docker service scale sistema_* =0).
  3. Snapshots/volumes: cópia via contêiner Alpine + tar em streaming evita salvar arquivos temporários.
  4. DNS: prepare um alias (ex.: vps2.esdrasrenan.com.br) e reduza o TTL dos CNAMEs antes do corte para minimizar caches antigos.
  5. TLS: copie acme.json entre as VPS e recarregue o Traefik para manter os certificados válidos após o corte.

3. Procedimento realizado

3.1. Inventário e auditoria

# CPU/memória, Swarm, stacks e volumes na VPS antiga
sshpass -p '...' ssh root@217.216.64.168 'lscpu; free -h; docker info; docker stack ls; docker stack services sistema; docker volume ls'

# Idem na VPS nova (confirmar recursos extras)
ssh -i codex_ed25519 root@154.12.253.40 'lscpu; free -h; docker stack ls; docker service ls'

3.2. Cópia inicial do código e volumes

# Código Next.js (bind mount)
sshpass -p '...' ssh root@217.216.64.168 'tar czf - -C /apps sistema'   | ssh -i codex_ed25519 root@154.12.253.40 'tar xzf - -C /apps'

# Volumes Docker em streaming (repetir para cada volume)
for vol in sistema_convex_data sistema_sistema_db sistema_db; do
  sshpass -p '...' ssh root@217.216.64.168     "docker run --rm -v $vol:/data alpine tar cz -C /data ."   | ssh -i codex_ed25519 root@154.12.253.40       "docker volume create $vol >/dev/null; docker run --rm -i -v $vol:/data alpine tar xz -C /data"
done

# Ajustar caminho esperado pelo serviço web
ssh root@154.12.253.40 'mkdir -p /home/renan/apps && mv /apps/sistema /home/renan/apps/ && ln -sfn /home/renan/apps/sistema /apps/sistema'

3.3. Recriação dos serviços no Swarm da VPS nova

Recriação manual (mais controle que o script) mantendo labels do Traefik:

# Convex backend
NET=traefik_public
STACK=sistema
**docker service create**   --name ${STACK}_convex_backend   --replicas 1   --constraint 'node.role == manager'   --network $NET   --mount type=volume,src=sistema_convex_data,dst=/convex/data   --limit-memory 12g   --env CONVEX_CLOUD_ORIGIN=https://convex.esdrasrenan.com.br   --env CONVEX_SITE_ORIGIN=https://convex.esdrasrenan.com.br   --env FLEET_SYNC_SECRET=...   --env MACHINE_PROVISIONING_SECRET=...   --env MACHINE_TOKEN_TTL_MS=2592000000   --env RUST_LOG=info   --label traefik.http.routers.sistema_convex.rule='Host(`convex.esdrasrenan.com.br`)'   ghcr.io/get-convex/convex-backend:latest

# Dashboard (mantido 0/0 até ser necessário)
docker service create ... --replicas 0 ghcr.io/get-convex/convex-dashboard:latest

# Web (Next.js/Bun)  notar bind mount + volume SQLite
docker service create   --name ${STACK}_web   --replicas 1   --constraint 'node.role == manager'   --network $NET   --mount type=bind,src=/home/renan/apps/sistema,dst=/app   --mount type=volume,src=sistema_sistema_db,dst=/app/data   --limit-memory 2g   --user 1000:1000   --workdir /app   --env NEXT_PUBLIC_APP_URL=https://tickets.esdrasrenan.com.br   --env NEXT_PUBLIC_CONVEX_URL=https://convex.esdrasrenan.com.br   --env CONVEX_INTERNAL_URL=http://sistema_convex_backend:3210   --env BETTER_AUTH_SECRET=...   --label traefik.http.routers.sistema_web.rule='Host(`tickets.esdrasrenan.com.br`)'   oven/bun:1.3.1 bash -lc 'bash /app/scripts/start-web.sh'

3.4. Certificados TLS

  1. Copiar acme.json das duas VPS.
  2. Mesclar certificados (para não perder a conta/chain nova) e reenviar para o volume certificados.
  3. Escalar traefik_traefik para 0, gravar o arquivo e retornar a 1.
sshpass -p '...' ssh root@217.216.64.168 'docker run --rm -v certificados:/data alpine cat /data/acme.json' > acme-old.json
ssh root@154.12.253.40 'docker run --rm -v certificados:/data alpine cat /data/acme.json' > acme-new.json
python3 merge_acme.py  # script que mescla Certificates
cat acme-merged.json | ssh root@154.12.253.40   'docker run --rm -i -v certificados:/data alpine sh -c "cat > /data/acme.json && chmod 600 /data/acme.json"'

3.5. Delta final antes do corte

  1. docker service scale sistema_* =0 na VPS antiga.
  2. Repetir o loop de volumes + tar do código para pegar qualquer alteração mais recente.
  3. Reaplicar chown -R 1000:1000 /home/renan/apps/sistema e re-symlink /apps/sistema.
  4. Forçar rolling update nos serviços da VPS nova:
ssh root@154.12.253.40 'docker service update --force sistema_convex_backend sistema_web'

3.6. DNS

  • Criado vps2.esdrasrenan.com.br (A → 154.12.253.40).
  • Atualizados os CNAMEs tickets.esdrasrenan.com.br e convex.esdrasrenan.com.br para apontar ao alias novo (TTL efetivo 300s após propagação).
  • Observação: durante ~4h alguns clientes ainda enxergaram o IP antigo porque o TTL prévio era 14.400s; na próxima migração, reduzir o TTL horas antes do corte para evitar 404 temporário.

3.7. Imagem Bun com OpenSSL

Para eliminar o warning do Prisma, foi criada uma imagem local (sistema-web:openssl-20251115) adicionando apt-get install openssl. Atualização do serviço:

ssh root@154.12.253.40 'docker build -t sistema-web:openssl-20251115 - <<"EOF"
FROM oven/bun:1.3.1
RUN apt-get update && apt-get install -y --no-install-recommends openssl \n  && rm -rf /var/lib/apt/lists/*
EOF'

docker service update --image sistema-web:openssl-20251115 sistema_web

Atenção: essa imagem só existe localmente; se outro nó entrar no Swarm, publique-a em um registry ou reconstrua no novo nó antes de escalar o serviço.

4. Verificações pós-migração

  • docker service ls | grep sistemaconvex_backend 1/1, web 1/1, dashboard 0/0.
  • curl -k -I --resolve tickets.esdrasrenan.com.br:443:154.12.253.40 https://tickets.esdrasrenan.com.br → 307 /login.
  • curl -k -I --resolve convex.esdrasrenan.com.br:443:154.12.253.40 https://convex.esdrasrenan.com.br → 200.
  • docker logs <container web> sem warnings de OpenSSL.
  • dig @1.1.1.1 +short tickets.esdrasrenan.com.brvps2.esdrasrenan.com.br154.12.253.40.

5. Recomendações para futuras trocas

  1. TTL primeiro, migração depois: reduza CNAMEs para 300s pelo menos 4h antes de alterar IPs.
  2. Dashboard opcional: mantenha sistema_convex_dashboard em 0/0 até precisar, escalando com docker service scale sistema_convex_dashboard=1.
  3. Imagem Bun custom: mantenha o Dockerfile acima em repositório (ex.: containers/sistema-web/Dockerfile) para reconstruções reproduzíveis.
  4. Rollback: para voltar à VPS antiga, restaure o DNS (CNAME → vps.esdrasrenan.com.br) e escale os serviços antigos para 1. Guarde a VPS por 2448h antes de desativá-la definitivamente.
  5. Logs: monitore docker service logs sistema_convex_backend para garantir que não haja exit 137. Se reaparecer, mantenha o limite de memória ≥ 12GB ou ajuste conforme uso real.

Com este fluxo documentado, repetir ou reverter a migração passa a ser um processo guiado e audível.