Desplegar el panel
El panel de empresa es un servicio pequeño y autoalojable: una API Node que sirve también el dashboard como ficheros estáticos. Esta es la guía de operaciones para IT: almacenamiento, la clave de firma, arranque del primer administrador y despliegue con Docker o Railway.
Requisitos
- Node 22.5 o superior si lo ejecutas directamente. Con Docker no necesitas nada más.
- Almacenamiento persistente: SQLite sobre un volumen o una base Postgres.
Almacenamiento
Dos backends sobre la misma interfaz:
- SQLite (por defecto): cero dependencias, un solo tenant. El fichero vive en la ruta de
PANEL_DB(por defectopanel.db). - Postgres / Neon: define
DATABASE_URL(para Neon, la cadena de conexión con?sslmode=require); tiene prioridad sobrePANEL_DB. El esquema se crea al arrancar y la clave de firma persiste en la base de datos, así los redespliegues son seguros por defecto.
La clave de firma: léelo antes de producción
El panel firma cada paquete (catálogo, contexto, packs) con su clave privada Ed25519 y cada equipo conectado fija la clave pública correspondiente al iniciar sesión.
Si la clave se regenera, todos los clientes dejan de confiar en el panel
Un redespliegue sin almacenamiento persistente genera una clave nueva. Todo equipo que fijó la clave pública anterior deja de verificar los paquetes y debe reconectarse. La clave debe sobrevivir a los redespliegues:
- En producción, entrégala con
PANEL_SIGNING_KEYdesde un KMS o gestor de secretos. Nunca en un repositorio, nunca en claro. - Con Postgres, la clave persiste en la base de datos automáticamente.
- Con SQLite, monta
PANEL_DBen un volumen (la imagen Docker usa/app/data/panel.dbexactamente por esto).
Perder la clave no es lo mismo que rotarla: la rotación planificada se hace desde la pestaña Keys del dashboard, conserva las claves anteriores en el conjunto de confianza y las sesiones vivas siguen verificando.
Primer administrador
Define PANEL_ADMIN_PASSWORD (y opcionalmente PANEL_ADMIN_IDENTITY, por defecto admin@corp). Al arrancar, el panel crea o resetea la cuenta de administrador, así un despliegue nuevo es administrable sin tocar la base de datos. Desde ahí, crea los usuarios reales en el dashboard: contraseñas de un solo uso que cada usuario rota en su primer acceso. Ver El panel, pestaña a pestaña.
Variables de entorno
| Variable | Para qué |
|---|---|
PANEL_DB |
ruta de la base SQLite (por defecto panel.db) |
DATABASE_URL |
cadena de conexión Postgres/Neon; gana a PANEL_DB |
PANEL_SIGNING_KEY |
clave de firma Ed25519 (producción: desde un KMS o gestor de secretos) |
PANEL_ADMIN_PASSWORD |
crea o resetea la cuenta de administrador al arrancar |
PANEL_ADMIN_IDENTITY |
identidad del administrador (por defecto admin@corp) |
PANEL_SUPER_ADMINS |
CSV de identidades marcadas como personal de plataforma: desbloquea la pestaña Tenants y el selector de organización en despliegues multi-tenant |
Docker
La imagen escucha en el puerto 8787 y usa PANEL_DB=/app/data/panel.db: monta un volumen en /app/data para que la clave de firma y el catálogo sobrevivan a los redespliegues.
docker build -t chronos-panel .
docker run -p 8787:8787 \
-v panel-data:/app/data \
-e PANEL_ADMIN_PASSWORD=<contraseñaInicial> \
chronos-panel
Al arrancar, el panel imprime los dos valores que los equipos necesitan para conectarse:
CHRONOS_PANEL_URL=http://127.0.0.1:8787
CHRONOS_PANEL_PUBKEY=<clave pública en hexadecimal>
Railway
El panel se despliega en Railway con la misma imagen. Dos puntos importan:
- Persistencia. O adjuntas un volumen de Railway en
/app/data(SQLite) o definesDATABASE_URLhacia Postgres/Neon. Con Postgres la clave de firma persiste en la base de datos y los redespliegues son seguros por defecto. - Variables. Define
PANEL_ADMIN_PASSWORD(yPANEL_SIGNING_KEYsi gestionas la clave fuera) como variables del servicio.
Conectar los equipos
Los desarrolladores conectan la app con el flujo de dispositivo: la app muestra un código, el usuario aprueba su máquina en la página de activación del panel y las claves públicas de firma quedan fijadas en el equipo. Ver El panel, pestaña a pestaña.
Para CI u operaciones, las variables de entorno tienen prioridad sobre el flujo de dispositivo:
export CHRONOS_PANEL_URL=https://<tuPanel>
export CHRONOS_PANEL_PUBKEY=<clavePublicaHex> # el cliente fija SOLO la clave pública
export CHRONOS_IDENTITY=<emailDelUsuario>
export CHRONOS_TEAMS=<equipoA>,<equipoB>
Sin CHRONOS_PANEL_URL el cliente funciona sin conexión y sin gobernanza central: la CI nunca necesita el panel.
Multi-tenant
Un mismo despliegue puede servir a varias organizaciones. Añade las identidades del personal de plataforma a PANEL_SUPER_ADMINS y esas cuentas verán la pestaña Tenants: crear organizaciones, ver su estado y administrar cualquiera de ellas. Cada organización tiene su propio catálogo, packs, contexto y usuarios; nada se cruza entre tenants. Ver Qué gobierna el panel.