Files
CloudRecoveryAS/INTEGRACION_PANEL.md

8.9 KiB

Integración CloudRestoreAS ↔ PANEL_BASES_ANEXO24

Variables de entorno y configuración

Panel (.env) CloudRestoreAS (pestaña Config → PANEL) Debe coincidir
CLOUDRESTORE_API_TOKEN panel.api_token — mismo valor en todas las instalaciones
ENCRYPTION_KEY Solo panel (cifra credenciales de restore_targets)
URL del panel (ej. https://panel:3000) panel.api_url — base URL sin barra final
panel.instance_key Nombre de este servidor en el panel (restore_targets.name)

Generar token:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Generar clave de cifrado (panel):

node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

BACKUP_PATH del panel es independiente: lista respaldos en el dashboard. Cada CloudRestoreAS reporta su carpeta local vía instance-config (clave = nombre del servidor).


Enrutamiento automático (todos los CRA)

No hay modos que configurar. Todo CRA con panel hace lo mismo:

  1. Llega un ZIP a la carpeta de entrada.
  2. GET resolve-route?filename=X&instance=<esta instancia> — el panel identifica el nodo y el servidor asignado.
  3. Si action=restore_local → extract + RESTORE aquí (credenciales SQL de este servidor en el panel).
  4. Si action=forward → SFTP del ZIP al input_folder del destino (credenciales SSH del destino).
  5. Mover ZIP a processed; reportar completed o forwarded.
flowchart TB
    ZIP[ZIP en carpeta local]
    CRA[Any CRA con instance_key]
    Panel["resolve-route"]
    SFTP[SFTP al destino]
    SQL[RESTORE local]

    ZIP --> CRA --> Panel
    Panel -->|restore_local| SQL
    Panel -->|forward| SFTP

Aplica igual en Alfa, Omega o un hub donde llegan todos los ZIP:

Situación Qué hace el CRA
Nodo asignado a esta instancia RESTORE local
Nodo asignado a otro servidor SFTP ZIP al destino

La decisión la toma el panel (nodo + asignación en Gestión BD), no el operador.

Qué configura cada instalación

Campo Para qué
URL + token del panel Conectar al panel
Instancia Identidad de este servidor (restore_targets.name)
Carpeta entrada Dónde vigila ZIPs esta máquina

El selector de instancia se llena desde GET /api/restore/target-catalog. No hay límite de servidores.

Hub donde llegan todos los ZIP

Ejemplo: máquina Alfa recibe todos los archivos y también tiene bases propias:

  1. Panel: servidor Alfa registrado; bases de Alfa/Omega/Gamma asignadas en Gestión BD.
  2. CRA en Alfa: instancia Alfa, misma URL/token que el resto.
  3. ZIP de base Alfa → RESTORE local.
  4. ZIP de base Omega → SFTP a carpeta de Omega (card Reportada).
  5. CRA Omega detecta el ZIP y restaura localmente.

No hay paso extra ni modo especial.

Sin panel (legacy local)

Si panel.api_url está vacío, CloudRestoreAS usa nodos SQLite locales y SQL de la pestaña Config (sin reparto automático).

Config legacy panel.mode

Valores antiguos (orchestrator, hub_restore, colocated) se ignoran. Se registra un aviso en log y se usa siempre resolve-route. El modo hub que subía .bak por SFTP ya no aplica.


Contrato API (/api/restore/*)

Autenticación: Authorization: Bearer <CLOUDRESTORE_API_TOKEN>.

GET /api/restore/target-catalog

Cliente: panel_client.list_restore_target_names()

Respuesta 200 Descripción
targets[] { "id", "name" } — sin credenciales

GET /api/restore/resolve-route?filename=<zip>&instance=<nombre>

Cliente: panel_client.resolve_route()

Query Obligatorio Descripción
filename Nombre del ZIP (panel resuelve nodo desde el stem)
instance Instancia de este CRA (restore_targets.name)
Respuesta 200 Descripción
action restore_local o forward
db_name Base resuelta
node_key Nodo en panel
target Servidor destino (SQL/SSH + input_folder)
Código Significado
404 Sin nodo/base o sin servidor asignado
503 Destino sin input_folder reportado

GET /api/restore/target-for?database=<db_name>&instance=<nombre>

Usado por utilidades legacy; el flujo principal de jobs usa resolve-route.

POST /api/restore/job-result

status: completed | failed | forwarded.

POST /api/restore/instance-config

Reporte de carpeta de entrada e identidad del agente (instance_key = nombre del servidor). Es best-effort: un fallo aquí nunca bloquea una restauración.

{
  "input_folder": "D:\\Backups\\Entrada",
  "processed_folder": "D:\\Backups\\Procesados",  // opcional; el panel la deriva si falta
  "host_name": "WIN-RESTORE-01",
  "app_version": "1.1.0",       // versión instalada → cloudrestore_status.app_version
  "platform": "windows",        // "windows" | "linux"
  "arch": "x86_64",             // "x86_64" | "arm64"
  "instance_key": "Alfa"        // = restore_targets.name
}

platform y arch le dicen al panel qué artefacto le corresponde a este servidor al instalar o actualizar: a24c.cras_releases se llavea por version + platform + arch. Un agente viejo que no las mande sigue funcionando; el panel cae al texto libre de restore_targets.os para la primera instalación.

Respuesta: 200 { "ok": true, "trace_id": "…" }.

POST /api/restore/agent-sync

Dispara la sincronización del catálogo de versiones contra Gitea. Lo usa publish-release.sh --notify-panel para que una versión recién publicada aparezca de inmediato, sin esperar a que un admin abra /versiones-cras.

Body vacío ({}). Respuesta: 200 { "ok": true, "discovered": N, "versions": N }.


Distribución de versiones (Gitea → PANEL → servidor)

Los binarios se publican en el registro de paquetes genéricos de Gitea; el panel los descubre leyendo su API, los cachea verificando el sha256 que Gitea calcula, e instala por SSH/SFTP en el servidor destino.

build local  →  Gitea (generic packages)  →  PANEL (caché + instalador SSH)  →  servidor
  • Publicar: ver BUILD.md §5 (publish-release.sh).
  • Instalar/actualizar: panel → Versiones CRAS (/versiones-cras) → Sincronizar con GiteaActivarInstalar en el servidor.
  • El panel siembra config/.env con api_url, api_token e instance_key durante la instalación, así que el servidor queda operativo sin configuración manual.
  • El servidor destino no descarga nada de internet: el binario es autocontenido y los bytes llegan del panel por SFTP.

Tablas involucradas: a24c.cras_releases (catálogo de versiones publicadas) y a24c.cras_install_runs (bitácora de instalaciones con progreso paso a paso).


Agregar servidores adicionales

  1. Panel → Servidores de Restauración → + Nuevo servidor (incluye credenciales SSH)
  2. Gestión de Bases de Datos → dropdown servidor por base
  3. Panel → Versiones CRASInstalar en ese servidor (siembra el .env solo)

El camino manual sigue disponible: instalar el CRA a mano → Config → instancia → Guardar (card Reportada).


Despliegue inicial

Orden de arranque (migraciones automáticas)

  1. a24c-postgres — volumen Postgres.
  2. a24c-backend — aplica alembic upgrade head al iniciar (incluye tablas CRA: restore_targets, restore_job_logs, cloudrestore_status, restore_target_id).
  3. Panel (docker compose up) — espera el esquema CRA en Postgres antes de abrir el puerto 3000.

No hace falta ejecutar database/migrations/*.sql a mano: la fuente de verdad es Alembic en a24c.

Panel

cd ~/dev/PANEL_BASES_ANEXO24
cp .env.example .env
docker compose up -d

Servidores de restauración + asignación de bases en Gestión BD.

Cada Windows con CloudRestoreAS

Config Valor
URL PANEL misma en todos
API Token mismo en todos
Instancia nombre de este servidor en panel
Carpeta Entrada local de esta máquina

Verificaciones

Paso Qué comprobar
Cards en panel Reportada con carpeta
ZIP propio RESTORE local
ZIP ajeno en esta carpeta SFTP al destino; bitácora forwarded
Destino recibe ZIP RESTORE local allí

Troubleshooting

  • Sin reportar: CRA destino no guardó config o no alcanza el panel.
  • 503 en forward: destino sin input_folder reportado.
  • Job diferido: panel caído, sin instance_key, o base sin asignación.
  • 401: token distinto entre panel y CRA.

Prueba local

Un CRA con instance_key igual al nombre en panel. El panel muestra una card por servidor; las no reportadas aparecen como Sin reportar.