Pasos para que un operador con acceso a prod despliegue con seguridad: env, build del frontend en CI, up del stack, seed + sync de permisos, smoke test y rollback. Incluye feature-flag SESSION_STORE_ENABLED como mitigación rápida. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.9 KiB
Runbook — Despliegue a PRODUCCIÓN · CRM Agente de Carga
Quién ejecuta: un operador con acceso al servidor de producción y a la base de datos de prod. Este runbook no lo ejecuta ningún agente automático. Prerrequisito de proceso: el PR de
feature/crm-workspace-altas-org-usuariodebe estar revisado y mergeado a la rama que corresponda antes de desplegar.Antes de empezar: respaldo. Toma un backup de la base
crm_corede prod (pg_dump) y del.envactual. Sin respaldo verificado, no continúes.
Este cambio es grande (auth/RBAC): login 100% vía Workspace/Hub, sesión local (patrón SIWEB), gestión de compañías/usuarios/roles y provisión vía Hub. Léelo completo antes de tocar prod.
0. Alcance del cambio
- Auth: el login deja de hablar directo con Keycloak; todo pasa por el Hub
(App Launcher →
/auth/sso?relay=<uuid>→POST {HUB_URL}/api/v1/auth/sso-exchange). - Sesión local: cookie de sesión propia (HS256) + token KC guardado en valkey
por
crm_sid. Requiere valkey arriba. Se controla conSESSION_STORE_ENABLED. - RBAC/Compañías: compañías en
a76.companypor tenant; roles por carril (Ventas, Operaciones, Facturación, Consulta); permisos por módulo.
Migraciones de esquema: este set no agrega tablas nuevas (usa core.*,
a76.company y valkey). Aun así, verifica migraciones pendientes en prod antes
de desplegar (paso 5). No corras migraciones a ciegas.
1. Prerrequisitos de infraestructura
- DNS de prod (p. ej.
crm.aduanasoft.com) apuntando al server de prod. - Docker + Docker Compose en el server.
- Servicios del stack:
backend,frontend,postgres,valkey,minio,celery_worker,celery_beat. - valkey operativo (lo usan la sesión local y
hub_token). - nginx + TLS (certbot) para servir app + API en el mismo origen.
- Acceso al Hub de producción (no el de testing) y al client/realm correctos.
2. Variables de entorno (.env en el server de prod)
Basado en deploy/env.testing.example, pero con hosts, dominio y secretos de
producción. Nunca subas el .env con secretos al repo.
# --- Seguridad ---
ENVIRONMENT=production
DEV_LOCAL_AUTH=false
SECRET_KEY=<openssl rand -hex 32>
# --- Sesión local (patrón SIWEB) ---
SESSION_STORE_ENABLED=true
SESSION_IDLE_MINUTES=30
SESSION_MAX_HOURS=10
VALKEY_URL=redis://valkey:6379/0
# --- Workspace / Hub de PRODUCCIÓN (mismo Hub que genera el relay) ---
WORKSPACE_URL=https://<hub-produccion>
HUB_URL=https://<hub-produccion>
INTERNAL_HUB_URL=https://<hub-produccion>
VITE_HUB_URL=https://<hub-produccion>
# --- Keycloak (single-realm / single-client) ---
KEYCLOAK_URL=https://<keycloak-produccion>/kcauth
VITE_KEYCLOAK_URL=https://<keycloak-produccion>/kcauth
KEYCLOAK_REALM=master
KEYCLOAK_CLIENT_ID=aduanasoft
KEYCLOAK_CLIENT_SECRET=<secret del producto provisionado en prod>
# --- Dominio del CRM (mismo origen app + API vía nginx) ---
ORIGIN=https://<dominio-crm-produccion>
APP_PUBLIC_URL=https://<dominio-crm-produccion>
VITE_API_URL=https://<dominio-crm-produccion>/api/
INTERNAL_API_URL=http://backend:8000/api/
CORS_ORIGINS=https://<dominio-crm-produccion>
# --- PostgreSQL ---
CORE_DB_HOST=postgres
CORE_DB_PORT=5432
CORE_DB_NAME=crm_core
CORE_DB_USER=<usuario>
POSTGRES_APP_PASSWORD=<password fuerte>
# --- MinIO / S3 ---
S3_ENDPOINT_URL=http://minio:9000
S3_ACCESS_KEY=<access>
S3_SECRET_KEY=<secret>
S3_BUCKET=crm
S3_REGION=us-east-1
S3_USE_SSL=false
Importante:
ENVIRONMENT=productionhace que el bootstrap de permisos solo désuper_adminal primer usuario (no a todos). Es el comportamiento deseado en prod.
3. Build del frontend — en CI, no en el server
La VM de prod no debe compilar el frontend (el build satura RAM). Compila la imagen en Jenkins/CI y publícala al registry, o compílala en una máquina de build:
docker compose -f docker-compose.yml -f docker-compose.prod.yml build frontend
# push al registry interno si aplica
El backend usa la imagen/código directamente (uvicorn sin --reload).
4. Despliegue
# En el server de prod, en el directorio del proyecto:
docker compose -f docker-compose.yml -f docker-compose.prod.yml pull # si usas registry
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker compose ps # verifica que todos queden healthy
5. Post-despliegue (datos) — operador humano, con respaldo hecho
- Verificar migraciones pendientes (si el proyecto usa Alembic u otro): revisar y aplicar solo las que correspondan, con backup previo.
- Seed base (compañía por tenant + carriles), equivalente a
seed_crm.py(ensure_company+ roles Ventas/Operaciones/Facturación/Consulta). - Sync de permisos (registra el catálogo por módulo):
docker compose exec backend python -c "from api.v1.modules.core.permissions.service import PermissionService; from core.database import CoreSessionLocal; PermissionService(CoreSessionLocal()).sync_permissions()"
6. Verificación / smoke test
curl -fsS https://<dominio-crm-produccion>/api/health && echo OK
- Login vía App Launcher del Workspace entra sin bucle.
- El dashboard carga compañías del tenant (switcher con el tenant correcto).
- Usuarios: lista carga tras refrescar; alta por invitación crea enlace.
- Roles y permisos: catálogo por módulo carga; marcar un permiso lo guarda (toast) y persiste al refrescar.
- Licencia válida (sin bucle 401 / "sesión expirada").
7. Rollback
docker compose ... up -dcon la imagen/tag anterior del frontend/backend.- Restaurar
.envanterior si se cambió. - Restaurar el backup de
crm_coresolo si hubo cambios de datos irreversibles. SESSION_STORE_ENABLED=falserevierte al comportamiento previo de sesión sin redeploy de código (feature-flag), como mitigación rápida.