Migração do Rastro → máquina nova (Gitea + Coolify)

Guia para mover a produção do Rastro (hoje em Docker Swarm na VPS 136.0.53.6) para a máquina nova, que usa Coolify e um Gitea interno (git + registro de imagem Docker).

Escopo: migra a ESTRUTURA (o stack) + só os DADOS DE USUÁRIO/CONFIG. Documentos, passagens, rotas e mídias NÃO vão (já foram limpos; a base voltou a ~1,6 GB).


Realidade do Rastro (importante)

Não é uma imagem única. São 2 imagens custom + 5 de infra públicas:

Imagem Origem Serviços
rastro-node build local → Gitea backend, web, admin, ingestor, processor, dfe-worker, migrate
rastro-analytics build local → Gitea analytics (Python)
timescale/timescaledb-ha:pg16 Docker Hub db
rabbitmq:3-management Docker Hub rabbitmq
minio/minio:latest Docker Hub minio
gotenberg/gotenberg:8 Docker Hub gotenberg
osrm/osrm-backend:latest Docker Hub osrm (opcional)

Por isso o deploy no Coolify é via Docker Compose (deploy/coolify-compose.yml), não "1 app = 1 imagem".

Registro — mesmo Gitea, duas rotas:

  • PUSH (build de fora, ex.: VPS antiga/seu Mac): gitea.externo.utic.app.br — o único que resolve fora da rede da UTIC (o interno deu timeout).
  • PULL (Coolify, que é interno): gitea.interno.utic.app.br — é o hostname que a máquina do Coolify enxerga, e sem credencial (interno). É o que vai nas image: do compose.

As imagens já estão publicadas (namespace ericoalmeida): …/ericoalmeida/rastro-node:latest e …/ericoalmeida/rastro-analytics:latest. Veja em https://gitea.externo.utic.app.br/ericoalmeida/-/packages. (docker.bretones.app que o Leo citou é o registro de OUTRO projeto dele — não é o nosso.)


Pré-requisitos (você faz no navegador)

  1. Usuário no Gitea em https://gitea.externo.utic.app.br (crie ou use o seu).
  2. Token de escrita de pacote: Settings → Applications → Generate New Token com o escopo de write:package (registro Docker). Guarde o token.
  3. Anote seu namespace (o usuário/organização — ex.: erico). As imagens vão para gitea.externo.utic.app.br/<namespace>/rastro-node:latest.

Fase 1 — Enviar as imagens para o Gitea

De uma máquina que alcança gitea.externo.utic.app.br e tem o repo (a VPS antiga serve — é amd64 e rápida; ou seu Mac). Na raiz do repo:

make login NAMESPACE=<seu-namespace>       # docker login (usuário + token)
make deploy NAMESPACE=<seu-namespace>      # build + push das 2 imagens

make deploy = build (--platform linux/amd64) + push. Se a máquina nova for arm64, rode make deploy PLATFORM=linux/arm64 (buildando no Mac, que é ARM nativo).

Confirme no Gitea (aba Packages do seu usuário) que rastro-node e rastro-analytics aparecem.


Fase 2 — Subir o stack no Coolify

  1. No Coolify: New Resource → Docker Compose.
  2. Cole o conteúdo de deploy/coolify-compose.yml.
  3. Environment variables: use deploy/.env.coolify.example como base. Preencha os segredos/cert/ONE com os valores reais (copie de /opt/rastro/.env da VPS antiga — posso transferir por scp). Ajuste WEB_DOMAIN/ADMIN_DOMAIN para os domínios novos e REGISTRY/NAMESPACE.
  4. Registro privado: aponte o Coolify para o Gitea (Sources/Registries) com o mesmo usuário+token, para ele puxar rastro-node/rastro-analytics. (Se o Gitea for interno à máquina do Coolify, o pull é direto, sem credencial — como o Leo disse.)
  5. Domínios / roteamento (a parte fina): o front chama a API em same-origin (/api e /health no MESMO domínio). Configure no Coolify:
    • web → https://${WEB_DOMAIN} (porta 39000)
    • admin→ https://${ADMIN_DOMAIN} (porta 39020)
    • backend → responder ${WEB_DOMAIN}/api, ${WEB_DOMAIN}/health, ${ADMIN_DOMAIN}/api, ${ADMIN_DOMAIN}/health (porta 39010) — roteamento por PATH. Se o roteamento por path do Coolify complicar, a alternativa é dar ao backend um domínio próprio api.<dominio> e rebuildar web/admin com VITE_API_BASE_URL=https://api.<dominio> (o CORS já cobre isso via CORS_ORIGINS).
  6. Deploy. Na 1ª subida, deixe ingestor e dfe-worker parados (scale 0) — sobem só quando você quiser puxar dados. O migrate roda uma vez (cria o schema) e sai.

Fase 3 — Restaurar os dados de usuário

O dump está em data-migration/rastro-userdata.sql (2,1 MB — usuários, RBAC, 5.922 pórticos, blacklist, thresholds de calibragem, ncm_ref, cursores).

Depois que o migrate criar o schema, carregue o dump no container do db (ex.: via terminal do Coolify no serviço db, ou docker exec):

# copie o arquivo para dentro do container do db, então:
psql -U rastro -d rastro -v ON_ERROR_STOP=1 <<'SQL'
BEGIN;
TRUNCATE app_user, role, permission, role_permission, user_role, user_session,
  equipment, volante_selection, ingestion_cursor, ingestion_control, ncm_ref,
  intel_threshold, entity_blacklist, blacklist_event, audit_log, access_request_log,
  process_lock RESTART IDENTITY CASCADE;
SQL
psql -U rastro -d rastro -f /caminho/rastro-userdata.sql   # tem SET session_replication_role p/ FK circular
psql -U rastro -d rastro -c "ANALYZE;"

O TRUNCATE antes evita conflito com qualquer linha que o schema-init tenha semeado. O dump já desabilita os triggers de FK (por causa da FK circular do app_user).

Login: os mesmos usuários da VPS antiga (ex.: ericoengcomp@gmail.com). Se preferir começar com um admin novo, dá pra semear com pnpm --filter @rastro/db seed (variáveis ADMIN_SEED_*).


Fase 4 — Certificado A1 e OSRM (quando precisar)

  • Certificado A1 (.pfx) — necessário para a drenagem/consultas SEFAZ. Copie o .pfx da VPS antiga (/opt/rastro/certificado/) para CERT_HOST_DIR na máquina nova e confira DFE_CERT_PFX_CONTAINER_PATH/DFE_CERT_PASSPHRASE. Sem ele, ingestor/dfe-worker não autenticam no fisco (mas o resto do sistema sobe).
  • OSRM (rotas no mapa) — descomente o serviço osrm no compose e leve o grafo do Brasil (brazil.osrm*, ~12-15 GB) para OSRM_DATA_DIR. Sem ele, o roteamento vira no-op (sem linhas no mapa) — aceitável até haver dado transacional de fato.

Verificação

  • web/admin abrem e o login funciona (usuário do dump).
  • Admin lista os 5.922 pórticos (equipment) e as permissões/roles.
  • migrate terminou como complete/exited 0; sem erro novo nos logs dos serviços.
  • Banco: SELECT count(*) FROM equipment; → 5922; FROM app_user; → seus usuários.

Rollback

A VPS antiga (136.0.53.6) continua intacta (stack fora do ar, volumes de 84→2,3 GB preservados). Nada aqui a toca — se algo falhar na máquina nova, a origem segue disponível.

S
Description
Compose + dados de migração do Rastro para deploy no Coolify
Readme
963 KiB