# Estratégia de Banco DEV — Relatório + Plano de Implementação > Documento de **decisão e plano** (16/jun/2026). A 1ª parte é o relatório técnico baseado em dados reais; a 2ª é o plano de implementação profissional, escalável para **todos os projetos atuais e futuros**. > Relacionado: `arquitetura.md`, `PENDENCIAS.md` (P0 isolar dev), `VERDADE-HOJE.md`. --- # PARTE 1 — Relatório técnico (dados reais, read-only) **Servidor (VPS3):** PostgreSQL **18.4** · **PostGIS 3.6.2** (suíte completa disponível). **Bancos (8 no total, ~175 MB somados):** | Banco | Tamanho | Projeto | DEV na VPS4? | Tabelas | Índices | PostGIS | |-------|--------:|---------|:------------:|--------:|--------:|:-------:| | newwhats | 91 MB | NewWhats (VPS1) | não | — | — | — | | giteadb | 22 MB | Gitea (infra) | não | — | — | não | | **scoreodonto** | **21 MB** | **ScoreOdonto** | **sim** | 104 | 168 | **SIM (3 geog)** | | mercado | 13 MB | Mercado (VPS1) | não | — | 187 | não | | **dental_images** | **11 MB** | **RX** | **sim** | 8 | 25 | não | | clube67 | 8.8 MB | Clube67 | não | — | — | — | | **subdominio** | **8 MB** | **Subdomínio** | **sim** | 3 | 7 | não | | postgres | 7.7 MB | default | — | — | — | — | **Conclusões:** - Os 3 bancos de DEV (scoreodonto, dental_images, subdominio) somam **~40 MB**. São minúsculos. - **Só o ScoreOdonto usa PostGIS.** RX e Subdomínio não. - Sem dependências entre bancos. Sem dados de crescimento histórico (não medível sem superuser); porte indica crescimento lento. **Veredito:** a proposta "mirror + dev por projeto" (6 containers PostgreSQL/PostGIS) é **viável mas exagerada** para esse porte. Um "mirror" *rodando* não agrega sobre um **template database** ou um **dump**; é só RAM e complexidade a mais (~300–600 MB RAM e 6× manutenção). **Recomendação final:** **um único container PostGIS na VPS4** (rootless), multi-banco, com `*_ref` (referência/template, restaurado da VPS3) + `*_dev` (de trabalho, criado via `CREATE DATABASE ... TEMPLATE`). Reset instantâneo, custo ~50–100 MB RAM, manutenção mínima, e **escala para qualquer projeto novo**. --- # PARTE 2 — Plano de implementação (profissional, escalável) > Objetivo: desgrudar **todos** os ambientes DEV do banco de produção (VPS3), com um padrão único que serve projetos atuais e futuros. **Produção (VPS3/VPS1) nunca é alterada — só lida (pg_dump).** ## 2.1 Arquitetura ``` VPS3 (produção, fonte da verdade) │ pg_dump (somente leitura, one-way) ▼ ┌──────────────── VPS4 (rootless) — container único "pgdev" ───────────────┐ │ postgis/postgis 18-3.6 (porta interna, rede 'soc', sem exposição pública) │ │ │ │ scoreodonto_ref ──TEMPLATE──► scoreodonto_dev ◄── backend dev ScoreOdonto │ │ dental_images_ref ─TEMPLATE──► dental_images_dev ◄── backend dev RX │ │ subdominio_ref ──TEMPLATE──► subdominio_dev ◄── backend dev Subdomínio │ │ _ref ──TEMPLATE──► _dev ◄── (projeto futuro) │ └────────────────────────────────────────────────────────────────────────────┘ ``` - **`*_ref`**: cópia fiel da produção (restaurada por `pg_dump`). Não se mexe — é a referência/"mirror". - **`*_dev`**: banco de trabalho, recriável do `_ref` em segundos via `TEMPLATE`. É onde rodam migrações e testes. - **Um container só** atende todos (Postgres lida com dezenas de bancos pequenos sem esforço). PostGIS coberto para quem precisa (ScoreOdonto); os demais simplesmente não usam. ## 2.2 Componentes (a criar em `/home/deploy/stack/pg-dev/`) **a) `docker-compose.yml`** (container do banco DEV): ```yaml services: pgdev: image: postgis/postgis:18-3.6 # confirmar tag p/ PG18+PostGIS3.6 (alt.: imresamu/postgis:18-3.6) container_name: pgdev restart: unless-stopped environment: POSTGRES_USER: devadmin POSTGRES_PASSWORD: ${PGDEV_PASSWORD} volumes: - pgdev-data:/var/lib/postgresql/data networks: [soc] # mesma rede dos backends de dev (acesso por DNS 'pgdev') # SEM ports: publicado → só acessível internamente (segurança) volumes: pgdev-data: networks: soc: external: true ``` **b) `pg-dev-projects.conf`** (manifesto — adicionar 1 linha por projeto novo): ``` # nome_projeto : banco_origem_VPS3 : usuario_origem scoreodonto : scoreodonto : scoreodonto_user rx : dental_images : clube67 subdominio : subdominio : mercado_admin ``` **c) `.env` / `secrets`** (gitignored, fora do repo): senha do `pgdev` (`PGDEV_PASSWORD`) e as senhas de origem da VPS3. **Nunca** versionar. **d) `pg-dev-refresh.sh `** — atualiza o `_ref` a partir da VPS3 e recria o `_dev`: ``` 1. pg_dump -Fc da VPS3 (banco_origem) usando a credencial do manifesto (read-only). 2. DROP/CREATE _ref no pgdev; pg_restore do dump → _ref. 3. DROP _dev; CREATE DATABASE _dev TEMPLATE _ref. ``` **e) `pg-dev-reset.sh `** — reset rápido (sem ir à VPS3): ``` DROP _dev; CREATE DATABASE _dev TEMPLATE _ref; ``` ## 2.3 Apontar os backends de DEV para o pgdev (sem afetar produção) Parametrizar a `DATABASE_URL` no compose de cada projeto para usar variáveis com **default = produção**, e na VPS4 criar um `.env` (gitignored) que sobrescreve só no dev: ``` # no docker-compose.yml (default mantém produção intacta): DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@${DB_HOST:-10.99.0.3}:5432/${DB_NAME:-scoreodonto} # .env SÓ na VPS4 (dev): DB_HOST=pgdev DB_NAME=scoreodonto_dev DB_USER=devadmin DB_PASS= ``` - Na VPS1 (produção) não existe esse `.env` → resolve para `10.99.0.3/scoreodonto`. **Produção nunca muda.** - Rebuild/recreate do backend de dev → passa a falar com `pgdev`. ## 2.4 Passos de implantação (quando aprovado) 1. Criar `/home/deploy/stack/pg-dev/` com o compose + scripts + `.env` (secrets). 2. `docker compose up -d pgdev` (rootless) + adicionar `pgdev` à rede `soc`. 3. Rodar `pg-dev-refresh.sh scoreodonto` (e rx, subdominio) → cria os `_ref` e `_dev`. 4. Criar o `.env` de dev em cada projeto e recriar os backends de dev. 5. Verificar: `dev.scoreodonto.com/api/version` sobe; conferir que escrita em dev cai em `scoreodonto_dev` (e produção em `scoreodonto` permanece intacta). 6. (privacidade) opcional: script de anonimização de dados sensíveis nos `_dev`. ## 2.5 Operação do dia a dia - **Quer dados atualizados da produção?** `pg-dev-refresh.sh `. - **Sujou o dev e quer voltar ao limpo?** `pg-dev-reset.sh ` (segundos, via TEMPLATE). - **Projeto novo?** adiciona 1 linha no `pg-dev-projects.conf` + `pg-dev-refresh.sh `. Pronto — sem novo container. ## 2.6 Custo e ganho - **Custo:** 1 container (~50–100 MB RAM, ~100 MB disco). Disco da VPS4 hoje: ~64 GB livres → folga total. - **Ganho:** dev deixa de poder corromper produção; resets instantâneos; PostGIS coberto; padrão único que escala para N projetos sem multiplicar containers. ## 2.7 O que este plano deliberadamente NÃO faz - Não cria 2 containers por projeto (over-engineering p/ bancos de 8–21 MB). - Não usa réplica streaming (exigiria config superuser na VPS3 + WAL; canhão p/ 40 MB). - Não toca em produção (VPS3/VPS1) — refresh é one-way, só `pg_dump`. --- # PARTE 3 — Status de implementação (16/jun/2026) **Implementado em `/home/deploy/stack/pg-dev/`** (Docker rootless da VPS4): - ✅ Container **`pgdev`** (`postgis/postgis:18-3.6`) na rede `soc`, sem porta pública, volume `pgdev-data` em `/var/lib/postgresql`. - ✅ Scripts `pg-dev-refresh.sh` / `pg-dev-reset.sh` + manifesto `pg-dev-projects.conf` + `secrets.env` (gitignored). - ✅ Bancos criados (ref+dev): **scoreodonto** (20 MB, PostGIS 3.6.3, 1750 pacientes), **rx** (dental_images), **subdominio**. **Backends apontados (via `.env` gitignored + `DATABASE_URL`/`PG_*` parametrizados com default=produção):** - ✅ **ScoreOdonto** → `pgdev/scoreodonto_dev` (validado: backend conecta, migrações OK; `dev.scoreodonto.com` no ar). Exigiu ajuste de SSL no backend (não força SSL p/ host `@pgdev`). - ✅ **Subdomínio** → `pgdev/subdominio_dev` (env confirmado, site no ar). - ✅ **RX** → `pgdev/rx_dev` (`rx.scoreodonto.com` no ar). Solução: app adicionado à rede `soc` + `DB_HOST/DB_NAME` parametrizados; role `clube67` criado no pgdev com a senha do `.secrets` (assim DB_USER/senha não mudam). **Produção (VPS3/VPS1) intocada.** Para um projeto novo: adicionar linha no `pg-dev-projects.conf`, `SRC__PASS` no `secrets.env`, rodar `./pg-dev-refresh.sh ` e parametrizar o compose do projeto + `.env`.