Deploy
Status: HML pronto pra aplicar via Terraform. Prod em skeleton.
Visão geral
Infraestrutura no GCP gerenciada com Terraform. Arquitetura atual: single-VM com Docker Compose (GCE VM hospeda tudo — Postgres, Redis, 10 APIs Node, nginx servindo as 5 SPAs).
Esta topologia substitui a arquitetura managed (Cloud Run + Cloud SQL + Memorystore + LB) que a gente tentou inicialmente e foi bloqueada por org policies da org pai (iam.allowedPolicyMemberDomains impedindo allUsers em IAM, o que é requisito do Cloud Run público). O pivô pra VM foi pragmático: acesso público vira um firewall rule de rede (não IAM), que a policy não alcança.
Domínio atual: onlyfordev.xyz — temporário descartável. Quando chegar o domínio final, trocar em environments/*/terraform.tfvars + environment.prod.ts das SPAs + docker/.env (CORS_ORIGINS, SESSION_COOKIE_DOMAIN).
Subdomínios
Todos apontam pra uma única VM via DNS A record. Nginx dentro da VM roteia por Host header.
| Host | Serve |
|---|---|
cms.onlyfordev.xyz | SPA cms-web (estática, nginx root) |
hub.onlyfordev.xyz | SPA hub-web |
admin.onlyfordev.xyz | SPA adm-web |
editor.onlyfordev.xyz | SPA cms-editor (iframe Puck) |
media.onlyfordev.xyz | SPA cms-media (iframe galeria) |
cms-api.onlyfordev.xyz | Proxy → container cms-api:3000 |
hub-api.onlyfordev.xyz | Proxy → hub-api:3100 (+ SSE /events) |
platform-api.onlyfordev.xyz | Proxy → platform-api:3200 |
tenant-api.onlyfordev.xyz | Proxy → tenant-api:3201 |
user-api.onlyfordev.xyz | Proxy → user-api:3202 (login, sessão) |
webhook.onlyfordev.xyz | Proxy → hub-webhook:3002 |
monitor.onlyfordev.xyz | Proxy → hub-monitor:3010 |
render.onlyfordev.xyz | Proxy → cms-renderer:3001 (SSR sites) |
Arquitetura de compute
| Workload | Onde roda |
|---|---|
| APIs Node (10) | Containers Docker numa única GCE VM |
| Workers BullMQ (hub-runner, hub-scheduler) | Containers no mesmo compose |
| SPAs (5) | Build estático montado como volume no nginx |
| Nginx | Container — reverse proxy + SSL termination |
| Certbot | Container companion (renovação automática) |
Dados
| Recurso | Onde |
|---|---|
| PostgreSQL 16 | Container Postgres com volume pg_data |
| Redis 7 | Container Redis com AOF em volume redis_data |
| Object storage | Volume local (/opt/hypergestor/uploads) ou bucket |
| Registry | Artifact Registry no mesmo projeto GCP (pull de images |
| customizadas se/quando precisar — build é feito na VM) |
Autenticação e cookies de sessão
Toda API usa o authPlugin de @hg/core, que valida o cookie opaco hg_session contra Redis. O cookie é emitido pelo user-api no login.
Configuração em prod/HML
httpOnly: true,secure: true,sameSite: 'lax'domain: .onlyfordev.xyz— fluxo entre subdomínios (eTLD+1 comum)
Todos os subdomínios compartilham o mesmo domínio → SameSite=lax funciona (cross-subdomain é same-site). Iframes editor/media também passam cookies.
CORS
Cada API lê CORS_ORIGINS (env do docker-compose). Setar no docker/.env com as 5 SPAs:
CORS_ORIGINS=https://cms.onlyfordev.xyz,https://hub.onlyfordev.xyz,https://admin.onlyfordev.xyz,https://editor.onlyfordev.xyz,https://media.onlyfordev.xyz
SSE (/events no hub-api)
Nginx faz proxy com proxy_buffering off e proxy_read_timeout 24h pra suportar long-lived SSE.
Fase HML
- Região:
us-central1 - VM:
e2-medium(2 vCPU shared / 4GB RAM) — ~R$125/mês - Disco: 30GB PD-balanced — ~R$10/mês
- Crédito autopop360: R$1785 ativos cobrem ~13 meses
Decisões
- Single VM em vez de Cloud Run — evita org policy + sem limite de backend buckets
- Postgres containerizado em vez de Cloud SQL — sem HA/backups managed (trocar por dumps periódicos)
- Redis AOF no volume local — sobrevive restart, não sobrevive destroy
- Let's Encrypt wildcard via webroot — certbot companion renova a cada 12h
- Deletion protection off em HML — pra iterar rápido
Fase Produção — a definir
Mesma topologia como ponto de partida (single-VM e2-standard-2) com:
deletion_protection = truena VM- Disco maior (50-100GB)
- Backups do Postgres via cron rodando
pg_dumppra GCS - Domínio real (não descartável)
- Migrar pra Cloud SQL/Memorystore quando o uso pedir (PR dedicada)
Pipelines de deploy
Subida inicial (HML)
# 1. Provisionar infra
cd infra/environments/hml
terraform init
terraform apply
# 2. Delegar DNS no Namecheap → NS do Cloud DNS (terraform output)
# 3. Rodar migrations + seed
pnpm deploy:migrate --seed
# 4. Acessar https://admin.onlyfordev.xyz
Deploy recorrente
# Push no código → deploy na VM
pnpm deploy:vm [branch]
# Só migrations
pnpm deploy:migrate
Os scripts SSH pra VM, fazem git pull, rebuildam SPAs e reciclaram os containers.
Rollback
ssh joao@<VM_IP>
cd /opt/hypergestor
git checkout <commit-anterior>
cd docker && docker compose up -d --build