Skip to main content

Entornos (pre / prod)

Principio

Un entorno = una copia corriendo completa del stack (frontend + backend + base de datos, apuntando a su propio ajolote). Es el mismo código/imagen desplegado dos veces, cada deploy con sus propias variables. No es un proceso compartido cambiando de DB: un proceso solo pertenece a un entorno, porque MikroORM se conecta a una sola DB al forRoot y el backend valida el token contra un solo ajolote (AUTH_SERVICE_URL fijo al boot).

PROD: pupo-panel.pages.dev → pupo.anfibia.io → db "id" → ajolote prod (público)
PRE: dev.pupo-panel.pages.dev → pupo-pre.anfibia.io → db "pupo_pre" → ajolote dev (Tailscale)

Ramas → entorno

Cada servicio (back en Dokploy, front en Cloudflare Pages) trackea una rama y el push dispara el build de ese entorno:

RamaEntorno
devPre
masterProducción

Flujo: features → dev (deploya pre) → validar → promover a master (deploya prod). auth-panel y auth-panel-front son repos separados; usar los mismos nombres de rama en ambos.

Base de datos

Ambos entornos comparten la misma instancia de PostgreSQL (en Dokploy), con una base de datos distinta por entorno:

VarProdPre
DB_NAMEidpupo_pre
DB_USERanfibioanfibio
DB_HOSTdatabases-postgresqldb-rw2aop (host interno de Dokploy)igual
DB_PORT5432igual
DB_SSLfalse (red interna)igual

La base de pre se creó a mano dentro de la misma instancia (conectado como el superusuario anfibio):

CREATE DATABASE pupo_pre;

Al ser anfibio el creador, queda como dueño y las migraciones crean solas los schemas app / configuration en el primer deploy (migration:up corre en el entrypoint).

:::warning Trade-off Se comparte el superusuario anfibio en ambos entornos, así que la separación es solo lógica (distinto DB_NAME), no a nivel credenciales. Si en el servicio de pre se pone DB_NAME=id por error, pega contra prod. Revisar bien el DB_NAME. Como blindaje futuro se puede dar a cada entorno un usuario dedicado con permisos solo sobre su base. :::

Fail-fast de configuración

mikro-orm.config.ts falla al arrancar si en producción (NODE_ENV=production) falta DB_NAME/DB_HOST/DB_USER/DB_PASSWORD, en lugar de caer a un fallback silencioso (enterprise_db/user/password) que podía conectar a la base equivocada. En dev se mantienen los defaults locales.

Redis

Ambos entornos comparten la misma instancia de Redis, aislados por índice de base lógica (REDIS_DB):

VarProdPre
REDIS_DB01

buildRedisUrl() (cache.module.ts) agrega /${REDIS_DB} a la URL. Redis solo se usa como cache (las sesiones viven en ajolote), así que compartir instancia con índices distintos alcanza.

Matriz de variables por entorno

Variables que cambian entre pre y prod:

VariableNota
DB_NAMEpupo_pre vs id
REDIS_DB1 (pre) vs 0 (prod)
AUTH_SERVICE_URLajolote de pre (Tailscale) vs ajolote de prod (público)
AJOLOTE_SERVICE_KEYdebe matchear TENANT_SYNC_SERVICE_KEY del ajolote del entorno
ENABLE_AUTH_PROXYtrue en pre, off en prod (ver Autenticación)
FRONT_URL / CORS_ORIGINdominio del front del entorno
NEW_RELIC_APP_NAMEPupo-pre vs Pupo (o NEW_RELIC_ENABLED=false en pre)

Iguales en ambos: DB_HOST, DB_PORT, DB_USER, DB_SSL, AUTH_APP_ID=pupo, NODE_ENV=production.