Infra (todo convive en la misma VPS, mismo addons_path read-only): - infra/clinica2/: odoo.conf (puerto 8070, db clinica2_odoo, data_dir propio), odoo-clinica2.service (sin env vars de WACRM/Supabase/Hermes), nginx-vhost (80 con server_name clinica2.consultoria-as.com + 8880 LAN, /api/odoo -> 8070, /wacrm/ cortado con 403), postinstall.py (brand neutro, menu WACRM vacio, admin con password propio y must_change_password) - docs/segunda-instancia.md: mapa completo de la instalacion, pasos para reproducir (instancia 3+), pendiente del hostname en dashboard del tunel (remotamente administrado), aislamiento de datos escenario B - frontend/public/brand/: logos SVG neutros + favicon para la instancia 2 Fix de menus (aplica a todas las instalaciones limpias, una sola pasada): - menu_skeen_root se mueve a skeen_pacientes (modulo raiz de la jerarquia); en bases existentes se transfirio el ownership del xmlid (ir_model_data) asi actualizar no duplica el menu - menu_skeen_citas (padre) se declara en skeen_citas/views/menus.xml que carga antes que bloqueo/lista_espera; menu_views.xml conserva las entradas con action (cargan despues de cita_views, donde se define la accion) - referencias actualizadas: pacientes(catalogos/recetas), monedero, ventas, inventario, visitas -> skeen_pacientes.menu_skeen_root Verificacion: produccion (skeen_odoo) actualizada sin duplicar menus y API intacta; instalacion limpia clinica2_odoo 9 modulos OK; 15/15 tests end-to-end (brand neutro, login admin, WACRM oculto+403, datos vacios)
4.6 KiB
Segunda instancia white-label (sin branding SKEEN)
Segunda clínica sobre el mismo código y la misma VPS. La marca no vive en el
código: sale del parámetro skeen.clinic.brand (ver GET /skeen/frontend/v1/brand),
así que esta y futuras instancias son solo infra + config.
Mapa de la instalación
| Componente | SKEEN (instancia 1) | Clínica 2 (instancia white-label) |
|---|---|---|
| Odoo HTTP | 8069 | 8070 |
| Odoo longpolling | 8072 | 8073 |
| Base de datos | skeen_odoo |
clinica2_odoo |
| Conf | /root/skeen-odoo/odoo.conf |
/root/clinica2-odoo.conf |
| Systemd | odoo-skeen.service |
odoo-clinica2.service |
| Frontend | /var/www/skeen-frontend |
/var/www/clinica2-frontend |
| Nginx | vhost skeen-crm (80) |
vhost clinica2 (80 + 8880) |
| Acceso LAN | http://192.168.10.114 | http://192.168.10.114:8880 |
| Acceso público | skeen.consultoria-as.com | clinica2.consultoria-as.com (pendiente: dashboard del túnel) |
| WhatsApp (WACRM) | integrado | oculto + bloqueado (escenario B) |
addons_path se comparte (read-only): /root/skeen-odoo/addons. Un solo
código, N bases de datos.
Cómo se levantó (orden de pasos)
Los archivos canónicos están en infra/clinica2/:
odoo.conf— copia del de SKEEN condb_name=clinica2_odoo,http_port=8070,longpolling_port=8073,data_dir=/var/lib/odoo-clinica2.- Crear la base (el rol
skeenno tiene CREATEDB; se crea comopostgres):CREATE DATABASE clinica2_odoo OWNER skeen ... - Instalar módulos limpio (sin demo):
odoo-bin -c /root/clinica2-odoo.conf -d clinica2_odoo --without-demo=all --init=skeen_whatsapp,skeen_chat,skeen_visitas --stop-after-init --no-http(skeen_whatsapp arrastra citas/pacientes/ventas/pagos/monedero; visitas arrastra inventario). postinstall.py— brand neutro (skeen.clinic.brand), menú WACRM vacío para todos (skeen.menu_roles), password de admin propio +must_change_password, empresa renombrada.systemctl enable --now odoo-clinica2.nginx-vhost→/etc/nginx/sites-enabled/clinica2+nginx -t && reload.- Frontend: mismo build de SKEEN (
rsync -a dist/ /var/www/clinica2-frontend/) máspublic/brand/(logos SVG neutros + favicon, versionados en el repo).
Pendiente para acceso público (único paso manual)
El túnel cloudflared corre con --token (remotamente administrado): el
config.yml local NO aplica. En el dashboard de Cloudflare (Zero Trust →
Networks → Tunnels → f2517233…) agregar el ingress:
- hostname: clinica2.consultoria-as.com
service: http://localhost:80
El vhost nginx ya escucha en el 80 con ese server_name; al agregar el
hostname el túnel enruta solo. El 8880 queda como acceso LAN permanente.
Aislamiento de datos (escenario B: sin WhatsApp)
- Sin
SUPABASE_URL/WACRM_API_*/HERMES_BRIDGE_URLen la unit systemd (el backend respondería "Falta configuración"). - Aun así, el backend tiene fallback a
localhost:3000; por eso el vhost nginx corta/api/odoo/skeen/frontend/v1/wacrm/conreturn 403;— doble candado, la instancia 2 no puede leer ni escribir las conversaciones de SKEEN aunque alguien llame la API a mano. - Menú WACRM oculto para todos los roles vía matriz (
/wacrm/*: []).
Para activar WhatsApp en la instancia 2 (escenario A) se necesita: número propio de WhatsApp Business + decisión de WACRM multi-clínica (estimar aparte).
Fix de menús que esta fase destapó (aplica a TODAS las instancias)
Las vistas XML referenciaban skeen_citas.menu_skeen_root, pero skeen_citas
depende de skeen_pacientes: en instalación limpia de una sola pasada el
xmlid aún no existe y la carga falla (la base de SKEEN se construyó por fases
y por eso nunca explotó). Se movió el menú raíz a skeen_pacientes (módulo
raíz de la jerarquía) y todas las referencias apuntan a
skeen_pacientes.menu_skeen_root. En bases existentes se transfirió el
ownership del xmlid (UPDATE ir_model_data SET module='skeen_pacientes' …),
así actualizar no duplica el menú. Mismo tratamiento para el menú padre de
Citas (skeen_citas/views/menus.xml carga antes que bloqueos/lista de espera).
Operación habitual
- Logs:
tail -f /tmp/odoo2.log(instancia 2) vs/tmp/odoo.log(SKEEN). - Ambas instancias comparten código: un
git pull+ rebuild afecta el build de ambas solo si se vuelven a copiar losdist/(cada uno tiene el suyo). - Para una tercera clínica: repetir pasos 1–7 con
clinica3(puertos 8074/8075, dbclinica3_odoo, vhost propio) y setear su brand desde Configuración → Clínica o conPUT /brand.