mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 11:23:18 +00:00
deploy: Liquibase automático en cada deploy (job migrate)
Coolify usa docker-compose.yml: migrate aplica schema (!dev) y la API espera a que termine. Postgres/Redis locales quedan en docker-compose.local.yml. Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
This commit is contained in:
parent
c2ea43818c
commit
a45675b6a6
6 changed files with 125 additions and 107 deletions
|
|
@ -14,4 +14,4 @@ COPY db/ ./db/
|
||||||
RUN chmod +x ./db/bootstrap-tools.sh ./db/update.sh && ./db/bootstrap-tools.sh
|
RUN chmod +x ./db/bootstrap-tools.sh ./db/update.sh && ./db/bootstrap-tools.sh
|
||||||
|
|
||||||
ENTRYPOINT ["./db/update.sh"]
|
ENTRYPOINT ["./db/update.sh"]
|
||||||
CMD ["all", "--context-filter=dev"]
|
CMD ["all", "--context-filter=!dev"]
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,10 @@ que el aislamiento realmente se cumple.
|
||||||
|
|
||||||
## Aplicar migraciones
|
## Aplicar migraciones
|
||||||
|
|
||||||
Requiere Java 17+ y las credenciales del rol `_owner` de cada módulo (nunca
|
En **Coolify** no se corre a mano: el servicio `migrate` de `docker-compose.yml`
|
||||||
`_app`, que es solo runtime):
|
aplica `all --context-filter=!dev` en cada deploy, antes de levantar `api`.
|
||||||
|
|
||||||
|
A mano (Java 17+ y credenciales `_owner`, nunca `_app`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Local, después de correr db/provision/dev-local.sh:
|
# Local, después de correr db/provision/dev-local.sh:
|
||||||
|
|
|
||||||
80
docker-compose.local.yml
Normal file
80
docker-compose.local.yml
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Desarrollo local: Postgres + Redis en compose, provision y seed `dev`.
|
||||||
|
# Uso: docker compose -f docker-compose.yml -f docker-compose.local.yml up --build
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASSWORD:?define POSTGRES_SUPERUSER_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
expose:
|
||||||
|
- "5432"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
expose:
|
||||||
|
- "6379"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
provision:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.provision
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
PGHOST: postgres
|
||||||
|
PGPASSWORD: ${POSTGRES_SUPERUSER_PASSWORD:?}
|
||||||
|
PLATFORM_OWNER_PASSWORD: ${PLATFORM_OWNER_PASSWORD:?}
|
||||||
|
PLATFORM_APP_PASSWORD: ${PLATFORM_APP_PASSWORD:?}
|
||||||
|
IAM_OWNER_PASSWORD: ${IAM_OWNER_PASSWORD:?}
|
||||||
|
IAM_APP_PASSWORD: ${IAM_APP_PASSWORD:?}
|
||||||
|
CORE_OWNER_PASSWORD: ${CORE_OWNER_PASSWORD:?}
|
||||||
|
CORE_APP_PASSWORD: ${CORE_APP_PASSWORD:?}
|
||||||
|
REDIS_ADMIN_URL: redis://redis:6379
|
||||||
|
IAM_REDIS_PASSWORD: ${IAM_REDIS_PASSWORD:?}
|
||||||
|
CORE_REDIS_PASSWORD: ${CORE_REDIS_PASSWORD:?}
|
||||||
|
command:
|
||||||
|
- -c
|
||||||
|
- "./db/provision/docker-provision.sh && ./db/provision/05-redis-acl.sh"
|
||||||
|
|
||||||
|
migrate:
|
||||||
|
depends_on:
|
||||||
|
provision:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
environment:
|
||||||
|
DATABASE_URL_PLATFORM_OWNER: postgresql://panels_platform_owner:${PLATFORM_OWNER_PASSWORD:?}@postgres:5432/panels_platform
|
||||||
|
DATABASE_URL_IAM_OWNER: postgresql://panels_iam_owner:${IAM_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
||||||
|
DATABASE_URL_CORE_OWNER: postgresql://panels_core_owner:${CORE_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
||||||
|
command: ["all", "--context-filter=dev"]
|
||||||
|
|
||||||
|
api:
|
||||||
|
depends_on:
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
DENO_ENV: development
|
||||||
|
DATABASE_URL_PLATFORM: postgresql://panels_platform_app:${PLATFORM_APP_PASSWORD:?}@postgres:5432/panels_platform
|
||||||
|
DATABASE_URL_IAM: postgresql://panels_iam_app:${IAM_APP_PASSWORD:?}@postgres:5432/panels_product
|
||||||
|
DATABASE_URL_CORE: postgresql://panels_core_app:${CORE_APP_PASSWORD:?}@postgres:5432/panels_product
|
||||||
|
DATABASE_URL_IAM_OWNER: postgresql://panels_iam_owner:${IAM_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
||||||
|
DATABASE_URL_CORE_OWNER: postgresql://panels_core_owner:${CORE_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
||||||
|
REDIS_URL_IAM: redis://panels_iam_redis:${IAM_REDIS_PASSWORD:?}@redis:6379
|
||||||
|
REDIS_URL_CORE: redis://panels_core_redis:${CORE_REDIS_PASSWORD:?}@redis:6379
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
|
@ -1,74 +1,19 @@
|
||||||
# Coolify / local — Postgres + Redis (ver plan de migración: monolito
|
# Coolify / producción — Postgres y Redis son recursos gestionados aparte.
|
||||||
# modular panels_platform / panels_product con esquemas iam+core).
|
# Liquibase corre solo en el job `migrate` (un shot por deploy); la API espera
|
||||||
# En Coolify, postgres/redis normalmente son recursos gestionados aparte
|
# a que termine. No arranca Java dentro del contenedor de tráfico.
|
||||||
# (ver docs/coolify.md); este compose incluye contenedores propios para
|
#
|
||||||
# que `docker compose up` funcione standalone en desarrollo local.
|
# Local: docker compose -f docker-compose.yml -f docker-compose.local.yml up --build
|
||||||
services:
|
services:
|
||||||
postgres:
|
|
||||||
image: postgres:16-alpine
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASSWORD:?define POSTGRES_SUPERUSER_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- postgres-data:/var/lib/postgresql/data
|
|
||||||
expose:
|
|
||||||
- "5432"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
restart: unless-stopped
|
|
||||||
expose:
|
|
||||||
- "6379"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
|
|
||||||
# Jobs de un solo uso (nunca en producción -- ver db/provision/README.md):
|
|
||||||
# 1) crea roles/bases/esquemas/ACLs, 2) aplica Liquibase. `api` espera a
|
|
||||||
# que ambos terminen bien antes de arrancar.
|
|
||||||
provision:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile.provision
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
PGHOST: postgres
|
|
||||||
PGPASSWORD: ${POSTGRES_SUPERUSER_PASSWORD:?}
|
|
||||||
PLATFORM_OWNER_PASSWORD: ${PLATFORM_OWNER_PASSWORD:?}
|
|
||||||
PLATFORM_APP_PASSWORD: ${PLATFORM_APP_PASSWORD:?}
|
|
||||||
IAM_OWNER_PASSWORD: ${IAM_OWNER_PASSWORD:?}
|
|
||||||
IAM_APP_PASSWORD: ${IAM_APP_PASSWORD:?}
|
|
||||||
CORE_OWNER_PASSWORD: ${CORE_OWNER_PASSWORD:?}
|
|
||||||
CORE_APP_PASSWORD: ${CORE_APP_PASSWORD:?}
|
|
||||||
REDIS_ADMIN_URL: redis://redis:6379
|
|
||||||
IAM_REDIS_PASSWORD: ${IAM_REDIS_PASSWORD:?}
|
|
||||||
CORE_REDIS_PASSWORD: ${CORE_REDIS_PASSWORD:?}
|
|
||||||
command:
|
|
||||||
- -c
|
|
||||||
- "./db/provision/docker-provision.sh && ./db/provision/05-redis-acl.sh"
|
|
||||||
|
|
||||||
migrate:
|
migrate:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.migrate
|
dockerfile: Dockerfile.migrate
|
||||||
depends_on:
|
restart: "no"
|
||||||
provision:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL_PLATFORM_OWNER: postgresql://panels_platform_owner:${PLATFORM_OWNER_PASSWORD:?}@postgres:5432/panels_platform
|
DATABASE_URL_PLATFORM_OWNER: ${DATABASE_URL_PLATFORM_OWNER:?}
|
||||||
DATABASE_URL_IAM_OWNER: postgresql://panels_iam_owner:${IAM_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
DATABASE_URL_IAM_OWNER: ${DATABASE_URL_IAM_OWNER:?}
|
||||||
DATABASE_URL_CORE_OWNER: postgresql://panels_core_owner:${CORE_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
DATABASE_URL_CORE_OWNER: ${DATABASE_URL_CORE_OWNER:?}
|
||||||
|
command: ["all", "--context-filter=!dev"]
|
||||||
|
|
||||||
api:
|
api:
|
||||||
build:
|
build:
|
||||||
|
|
@ -78,15 +23,14 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
migrate:
|
migrate:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
environment:
|
||||||
|
DENO_ENV: ${DENO_ENV:-production}
|
||||||
PORT: ${PORT:-8000}
|
PORT: ${PORT:-8000}
|
||||||
SESSION_SECRET: ${SESSION_SECRET}
|
SESSION_SECRET: ${SESSION_SECRET:?}
|
||||||
DOCS_KEY: ${DOCS_KEY}
|
DOCS_KEY: ${DOCS_KEY:?}
|
||||||
SEED_PASSWORD: ${SEED_PASSWORD}
|
SEED_PASSWORD: ${SEED_PASSWORD:-}
|
||||||
API_KEY: ${API_KEY:-}
|
API_KEY: ${API_KEY:-}
|
||||||
PANEL_LOGIN_URL: ${PANEL_LOGIN_URL}
|
PANEL_LOGIN_URL: ${PANEL_LOGIN_URL:?}
|
||||||
COOKIE_SECURE: ${COOKIE_SECURE:-true}
|
COOKIE_SECURE: ${COOKIE_SECURE:-true}
|
||||||
CORS_ORIGINS: ${CORS_ORIGINS:-}
|
CORS_ORIGINS: ${CORS_ORIGINS:-}
|
||||||
VCARD_BASE: ${VCARD_BASE:-}
|
VCARD_BASE: ${VCARD_BASE:-}
|
||||||
|
|
@ -95,21 +39,17 @@ services:
|
||||||
SMTP_USER: ${SMTP_USER:-}
|
SMTP_USER: ${SMTP_USER:-}
|
||||||
SMTP_PASS: ${SMTP_PASS:-}
|
SMTP_PASS: ${SMTP_PASS:-}
|
||||||
SMTP_FROM: ${SMTP_FROM:-}
|
SMTP_FROM: ${SMTP_FROM:-}
|
||||||
# Postgres: panels_platform (base separada) + panels_product (iam/core)
|
DATABASE_URL_PLATFORM: ${DATABASE_URL_PLATFORM:?}
|
||||||
DATABASE_URL_PLATFORM: postgresql://panels_platform_app:${PLATFORM_APP_PASSWORD:?}@postgres:5432/panels_platform
|
DATABASE_URL_PLATFORM_OWNER: ${DATABASE_URL_PLATFORM_OWNER:-}
|
||||||
DATABASE_URL_IAM: postgresql://panels_iam_app:${IAM_APP_PASSWORD:?}@postgres:5432/panels_product
|
DATABASE_URL_IAM: ${DATABASE_URL_IAM:?}
|
||||||
DATABASE_URL_CORE: postgresql://panels_core_app:${CORE_APP_PASSWORD:?}@postgres:5432/panels_product
|
DATABASE_URL_IAM_OWNER: ${DATABASE_URL_IAM_OWNER:?}
|
||||||
DATABASE_URL_IAM_OWNER: postgresql://panels_iam_owner:${IAM_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
DATABASE_URL_CORE: ${DATABASE_URL_CORE:?}
|
||||||
DATABASE_URL_CORE_OWNER: postgresql://panels_core_owner:${CORE_OWNER_PASSWORD:?}@postgres:5432/panels_product
|
DATABASE_URL_CORE_OWNER: ${DATABASE_URL_CORE_OWNER:?}
|
||||||
# Redis: ACLs por módulo (ver db/provision/05-redis-acl.sh)
|
REDIS_URL_IAM: ${REDIS_URL_IAM:?}
|
||||||
REDIS_URL_IAM: redis://panels_iam_redis:${IAM_REDIS_PASSWORD:?}@redis:6379
|
REDIS_URL_CORE: ${REDIS_URL_CORE:?}
|
||||||
REDIS_URL_CORE: redis://panels_core_redis:${CORE_REDIS_PASSWORD:?}@redis:6379
|
|
||||||
# Contabo Object Storage (Fase 4c) -- opcional; sin esto cae a disco
|
|
||||||
# local bajo el volumen panel-data (no recomendado en producción,
|
|
||||||
# ver plan: un volumen local no escala horizontalmente).
|
|
||||||
S3_ENDPOINT: ${S3_ENDPOINT:-}
|
S3_ENDPOINT: ${S3_ENDPOINT:-}
|
||||||
S3_BUCKET: ${S3_BUCKET:-}
|
S3_BUCKET: ${S3_BUCKET:-}
|
||||||
S3_REGION: ${S3_REGION:-}
|
S3_REGION: ${S3_REGION:-auto}
|
||||||
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-}
|
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-}
|
||||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-}
|
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-}
|
||||||
volumes:
|
volumes:
|
||||||
|
|
@ -156,5 +96,4 @@ services:
|
||||||
- "80"
|
- "80"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres-data:
|
|
||||||
panel-data:
|
panel-data:
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
| Postgres gestionado en Coolify | **1 instancia** por ambiente, con **2 bases**: `panels_platform`, `panels_product` (esquemas `iam`/`core`) |
|
| Postgres gestionado en Coolify | **1 instancia** por ambiente, con **2 bases**: `panels_platform`, `panels_product` (esquemas `iam`/`core`) |
|
||||||
| Redis gestionado en Coolify | **1 instancia** por ambiente, con **2 usuarios ACL** (`panels_iam_redis`, `panels_core_redis`) |
|
| Redis gestionado en Coolify | **1 instancia** por ambiente, con **2 usuarios ACL** (`panels_iam_redis`, `panels_core_redis`) |
|
||||||
| Object storage | Cloudflare R2 (S3-compatible) para expedientes/PDFs/logos cifrados |
|
| Object storage | Cloudflare R2 (S3-compatible) para expedientes/PDFs/logos cifrados |
|
||||||
| Contenedores de la app | **3** (`api`, `web-panel`, `web-saas`) |
|
| Contenedores de la app | **4** (`migrate` un shot por deploy + `api` + `web-panel` + `web-saas`) |
|
||||||
| Volumen persistente | **1** → `/app/data` en `api` (solo fallback local si no hay Contabo configurado -- no usar así en producción) |
|
| Volumen persistente | **1** → `/app/data` en `api` (solo fallback local si no hay Contabo configurado -- no usar así en producción) |
|
||||||
|
|
||||||
Los fronts (Alpine + nginx) hacen proxy de `/v1` al servicio `api`, así las cookies de sesión van same-origin.
|
Los fronts (Alpine + nginx) hacen proxy de `/v1` al servicio `api`, así las cookies de sesión van same-origin.
|
||||||
|
|
@ -36,6 +36,7 @@ distintos dentro de `panels_product`, y las reglas del monolito modular.
|
||||||
| `SEED_PASSWORD` | string | Password inicial usado por `api/scripts/bootstrap-admin.ts` |
|
| `SEED_PASSWORD` | string | Password inicial usado por `api/scripts/bootstrap-admin.ts` |
|
||||||
| `PANEL_LOGIN_URL` | URL absoluta | Link en correos de acceso |
|
| `PANEL_LOGIN_URL` | URL absoluta | Link en correos de acceso |
|
||||||
| `DATABASE_URL_PLATFORM` | `postgresql://panels_platform_app:...@host:5432/panels_platform` | Runtime, rol `_app` |
|
| `DATABASE_URL_PLATFORM` | `postgresql://panels_platform_app:...@host:5432/panels_platform` | Runtime, rol `_app` |
|
||||||
|
| `DATABASE_URL_PLATFORM_OWNER` | igual, rol `_owner` | Job `migrate` (Liquibase SaaS) |
|
||||||
| `DATABASE_URL_IAM` | `postgresql://panels_iam_app:...@host:5432/panels_product` | Runtime, rol `_app`, esquema `iam` |
|
| `DATABASE_URL_IAM` | `postgresql://panels_iam_app:...@host:5432/panels_product` | Runtime, rol `_app`, esquema `iam` |
|
||||||
| `DATABASE_URL_CORE` | `postgresql://panels_core_app:...@host:5432/panels_product` | Runtime, rol `_app`, esquema `core` |
|
| `DATABASE_URL_CORE` | `postgresql://panels_core_app:...@host:5432/panels_product` | Runtime, rol `_app`, esquema `core` |
|
||||||
| `DATABASE_URL_IAM_OWNER` | igual, rol `_owner` | Solo para el lookup de login por username (bypassa RLS a propósito, ver `api/iam_db.ts`) |
|
| `DATABASE_URL_IAM_OWNER` | igual, rol `_owner` | Solo para el lookup de login por username (bypassa RLS a propósito, ver `api/iam_db.ts`) |
|
||||||
|
|
@ -83,29 +84,25 @@ En Coolify el servicio de PANELS se llama **`web-panel`** (FQDN ej. `panels.mrde
|
||||||
|
|
||||||
1. **Provisionar Postgres, Redis y bucket** — 1 de cada **por ambiente** (no por módulo; no compartir prod con staging).
|
1. **Provisionar Postgres, Redis y bucket** — 1 de cada **por ambiente** (no por módulo; no compartir prod con staging).
|
||||||
2. **Crear accesos y validar**: `./db/provision/create-accesses.sh --apply --verify --out .env.<env>.local` contra esos hosts (ver [`db/provision/README.md`](../db/provision/README.md)). Coolify no crea los roles `panels_*` ni los ACL de Redis solo.
|
2. **Crear accesos y validar**: `./db/provision/create-accesses.sh --apply --verify --out .env.<env>.local` contra esos hosts (ver [`db/provision/README.md`](../db/provision/README.md)). Coolify no crea los roles `panels_*` ni los ACL de Redis solo.
|
||||||
3. **Aplicar Liquibase** (paso explícito, NO ocurre al arrancar la app): `./db/update.sh all --context-filter='!dev'` con las credenciales `_owner`. En staging/producción, **nunca** olvidar el `--context-filter` -- sin él, Liquibase corre TAMBIÉN los changesets de demo (`context=dev`).
|
3. **Coolify → Docker Compose** → `docker-compose.yml` (este archivo **no** levanta Postgres/Redis; usa los recursos que ya creaste). Conecta el stack a la **misma red** que Postgres y Redis (Connect to Predefined Network).
|
||||||
4. **Bootstrap del primer admin**: `deno run ... api/scripts/bootstrap-admin.ts platform` y `... tenant --tenant-id=... --company-code=...` (ver `db/README.md`).
|
4. Cargar en el recurso compose **todas** las variables obligatorias (incluidas las 3 `DATABASE_URL_*_OWNER`: las usa el job `migrate`). `DENO_ENV=production`.
|
||||||
5. **Push** este repo (sin `.env` ni `data/`).
|
5. **Deploy.** En cada deploy corre `migrate` (`--context-filter=!dev`, sin demo) y **después** arranca `api`. No hace falta entrar al VPS a correr Liquibase.
|
||||||
6. Coolify → **New Resource → Docker Compose** → `docker-compose.yml` (solo para `api`/`web-panel`/`web-saas` -- si Postgres/Redis ya son recursos gestionados aparte, quitar esos servicios del compose antes de desplegar, o apuntar sus variables a los recursos gestionados en vez de los contenedores locales del compose).
|
6. **Bootstrap del primer admin** (solo la primera vez): `bootstrap-admin.ts` (ver `db/README.md`).
|
||||||
7. **Persistent storage:** volumen `panel-data` → `/app/data` en `api` (solo fallback de archivos si no hay Contabo).
|
7. **Persistent storage:** volumen `panel-data` → `/app/data` en `api` (solo fallback si no hay R2).
|
||||||
8. **Dominios:** `web-panel` → panels; `web-saas` → saas; `api` sin FQDN (proxy `/v1`).
|
8. **Dominios:** `web-panel` → panels; `web-saas` → saas; `api` sin FQDN (proxy `/v1`).
|
||||||
9. Cargar en Coolify todas las variables **obligatorias** de la tabla de arriba + `COOKIE_SECURE=true`.
|
9. Verificar `https://app…/v1/health` → `ok`, `core`, `platform`, `redis.iam`, `redis.core` y `storage` (en prod `backend:"s3"`). Si algo falla, la API no arranca.
|
||||||
10. Deploy.
|
10. Login SaaS `admin` / tu `SEED_PASSWORD` (tras el bootstrap).
|
||||||
11. Verificar `https://app…/v1/health` → `ok`, `core`, `platform`, `redis.iam`, `redis.core` y `storage` (en prod `backend:"s3"`). Si algo falla, la API no arranca.
|
11. SMTP en `/smtp` o por `SMTP_*`.
|
||||||
12. Login SaaS `admin` / tu `SEED_PASSWORD`.
|
|
||||||
13. SMTP en `/smtp` o por `SMTP_*`.
|
|
||||||
|
|
||||||
## Local (todo en docker-compose, incluyendo Postgres/Redis propios)
|
## Local (todo en docker-compose, incluyendo Postgres/Redis propios)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .env.example .env # rellenar TODAS las variables (incluye los passwords de roles Postgres/Redis)
|
cp .env.example .env
|
||||||
docker compose up --build
|
docker compose -f docker-compose.yml -f docker-compose.local.yml up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
El compose local incluye: `provision` (roles/esquemas/ACLs, un solo uso) →
|
El overlay local añade Postgres/Redis + `provision` y corre Liquibase con `context=dev` (demo).
|
||||||
`migrate` (Liquibase con datos de demo, un solo uso) → `api`/`web-panel`/`web-saas`.
|
En Coolify solo se usa `docker-compose.yml`: `migrate` con `!dev`.
|
||||||
Para producción, `provision`/`migrate` NO se corren así -- ver
|
|
||||||
`db/provision/README.md` y `db/RUNBOOK-corte.md`.
|
|
||||||
|
|
||||||
Sin las variables obligatorias, compose **no arranca** (`:?` en docker-compose.yml).
|
Sin las variables obligatorias, compose **no arranca** (`:?` en docker-compose.yml).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
"dev:web": "cd web-panel && npm run dev",
|
"dev:web": "cd web-panel && npm run dev",
|
||||||
"dev:saas": "cd web-saas && npm run dev",
|
"dev:saas": "cd web-saas && npm run dev",
|
||||||
"db:migrate": "./db/update.sh all",
|
"db:migrate": "./db/update.sh all",
|
||||||
"docker:build": "docker compose build",
|
"docker:build": "docker compose -f docker-compose.yml -f docker-compose.local.yml build",
|
||||||
"docker:up": "docker compose up -d"
|
"docker:up": "docker compose -f docker-compose.yml -f docker-compose.local.yml up -d"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue