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

134 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 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
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.