8.1 KiB
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 / 8 GB | 8 vCPU / 24 GB |
| 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 (5 GB) |
/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 usandoservices.json.
2. Pré-requisitos e boas práticas
- Autenticação: senha root na VPS antiga (
sshpass) e chavecodex_ed25519para a nova (chmod 600). - Congelamento de escrita: antes do delta final, escalar a 0 os serviços que escrevem (
docker service scale sistema_* =0). - Snapshots/volumes: cópia via contêiner Alpine + tar em streaming evita salvar arquivos temporários.
- DNS: prepare um alias (ex.:
vps2.esdrasrenan.com.br) e reduza o TTL dos CNAMEs antes do corte para minimizar caches antigos. - TLS: copie
acme.jsonentre 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
- Copiar
acme.jsondas duas VPS. - Mesclar certificados (para não perder a conta/chain nova) e reenviar para o volume
certificados. - Escalar
traefik_traefikpara 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
docker service scale sistema_* =0na VPS antiga.- Repetir o loop de volumes +
tardo código para pegar qualquer alteração mais recente. - Reaplicar
chown -R 1000:1000 /home/renan/apps/sistemae re-symlink/apps/sistema. - 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.breconvex.esdrasrenan.com.brpara apontar ao alias novo (TTL efetivo 300 s após propagação). - Observação: durante ~4 h alguns clientes ainda enxergaram o IP antigo porque o TTL prévio era 14.400 s; 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 sistema→convex_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.br→vps2.esdrasrenan.com.br→154.12.253.40.
5. Recomendações para futuras trocas
- TTL primeiro, migração depois: reduza CNAMEs para 300 s pelo menos 4 h antes de alterar IPs.
- Dashboard opcional: mantenha
sistema_convex_dashboardem0/0até precisar, escalando comdocker service scale sistema_convex_dashboard=1. - Imagem Bun custom: mantenha o Dockerfile acima em repositório (ex.:
containers/sistema-web/Dockerfile) para reconstruções reproduzíveis. - Rollback: para voltar à VPS antiga, restaure o DNS (CNAME →
vps.esdrasrenan.com.br) e escale os serviços antigos para1. Guarde a VPS por 24–48 h antes de desativá-la definitivamente. - Logs: monitore
docker service logs sistema_convex_backendpara garantir que não hajaexit 137. Se reaparecer, mantenha o limite de memória ≥ 12 GB ou ajuste conforme uso real.
Com este fluxo documentado, repetir ou reverter a migração passa a ser um processo guiado e audível.