Preparación para la recuperación
Libre WebUI ofrece un inventario de recuperación de solo lectura como primera barrera de seguridad. Informa del estado conocido y de las condiciones que bloquean una instantánea. No adquiere un bloqueo de mantenimiento ni copia, cifra, sube, elimina, repara o restaura datos.
libre-webui recovery-check --json > recovery-inventory.json
Desde el código, ejecuta una vez npm run build:backend y sustituye libre-webui recovery-check por
npm run recovery:check --. Las instalaciones npx y Homebrew inspeccionan ~/.libre-webui; DATA_DIR y rutas explícitas
lo sustituyen.
El estado de salida es 0 sin bloqueos, 1 con informe completo pero bloqueos y 2 por argumentos inválidos o fallo inesperado.
Usa --data-dir PATH o --database PATH. El inventario predeterminado solo acepta DATA_DIR/data.sqlite y rechaza base,
WAL o SHM enlazados, simbólicos o no regulares. Una --database explícita puede estar fuera, pero ella y sus acompañantes deben
ser archivos regulares no simbólicos. Sin --data-dir, su padre se trata como raíz para inventariar clave, blobs y plugins juntos.
El runtime también lee definiciones históricas desde el directorio plugins del paquete backend y, si PLUGINS_DIR es relativo,
su ubicación histórica. Esas rutas bloquean una instantánea solo del volumen si contienen definiciones personalizadas. Los despliegues
empaquetados pueden pasar varias veces --legacy-plugins-dir PATH.
En Compose privado, ejecútalo dentro del contenedor:
docker exec libre-webui \
libre-webui recovery-check --json --data-dir /app/backend/data
Qué comprueba el inventario
El informe JSON versionado registra:
- versiones de aplicación, Node.js, sistema y arquitectura;
- tamaños de SQLite/WAL/SHM,
quick_check, claves foráneas, huella del esquema, versión de usuario, tablas ausentes y validación sin seguir enlaces antes de crear una copia privada; - lectura, escritura, número de archivos y bytes del directorio;
- origen de clave y huella irreversible de 16 caracteres;
- validación sin enlaces y de vínculo único de
.encryption_key; - presencia, cantidad, tamaño e inclusión de plugins, blobs cifrados, medios, voces, texto, vectores heredados y de plataforma con ACL;
- autenticación limitada y de solo lectura de todos los blobs y envolturas vectoriales, con fragmentos, checksums y claves;
- autenticación de envolturas AES-GCM reconocibles en chats, notas, documentos, preferencias, secretos, galería, correo y voces vinculadas mediante AAD;
- tareas, ejecuciones y vistas de Work y sus volúmenes Docker, PVC Kubernetes o identidades de rutas; los volúmenes deben llevar etiqueta gestionada e ID exacto;
- estados de trabajos multimedia y duraderos, intentos, flujos, eventos y cursor global;
- autenticación de cargas cifradas y validación sintáctica limitada de referencias opacas; y
- bloqueos, advertencias y datos externos al directorio.
Nunca incluye claves, secretos JWT, credenciales, contenido de plugins o usuarios ni rutas literales del host. Solo emite presencia de secretos y la huella no reversible. Un montaje de solo lectura produce advertencia, no bloqueo, pero nunca inicies la aplicación contra la instantánea de solo lectura.
Bloqueos
Cualquier bloqueo hace fallar la barrera: base ausente o corrupta, esquema incompleto, clave ausente o conflictiva, ciphertext corrupto o no autenticado, límites excedidos, directorio ilegible, SQLite enlazado o irregular, ejecuciones, vistas o trabajos activos, workspace ausente o mal etiquetado, discrepancias o huecos de eventos, plugins externos o un plano de control incapaz de verificar workspaces. Detén la actividad y resuelve dependencias; no edites el informe para ocultarlo.
Las cargas duraderas se autentican contra la identidad y como JSON canónico limitado. Las referencias opacas solo se limitan y validan
sintácticamente porque no existe un repositorio autoritativo para probar el destino. El informe marca referenceTargetsVerified false
y advierte sin revelar valores.
Los campos heredados preceden al marcador obligatorio: el texto claro genuino sigue siendo legible y no cuenta como ciphertext.
Las envolturas canónicas siempre se autentican; valores de tres partes con IV o etiqueta de ancho de envoltura fallan cerrados si están
malformados. Las voces tienen una envoltura inequívoca vinculada a perfil, propietario y campo. encryption.legacyCiphertext informa
totales sin exponer texto.
Con users.email_lookup de v4, también se autentica cada correo y se recalcula su token separado por dominio. Un token ausente,
incorrecto o asociado a correo null bloquea. Las bases anteriores siguen siendo compatibles.
Límite actual de la copia
El asistente privado detiene la aplicación si estaba activa y usa imagen inmutable, volumen y entorno para crear un archivo solo.
El manifiesto se firma con Ed25519 y la carga completa se cifra con una clave AES-256-GCM del operador. Incluye SQLite, blobs,
vectores, selectores y configuración protegida. Verifica firma, checksum y carga antes de publicar. libre-webui-restore solo acepta
un volumen Docker nuevo, verifica el inventario y publica configuración privada en un directorio nuevo.
La configuración protegida incluye pool, conexión, inactividad, sentencias y bloqueo de migración PostgreSQL; conexión Redis; cuotas
de blobs; selectores; prefijo S3 y modo de direccionamiento. Está cifrada, no en el manifiesto claro, y se publica con modo 0600.
El archivo solo excluye volúmenes Work, PVC, carpetas del host, modelos Ollama y estado externo. Mantén visibles las exclusiones y respalda Work por separado. El perfil team usa un flujo offline: snapshot PostgreSQL, objetos S3 versionados, inventario PGVector, configuración e identidad de clave en el mismo formato, verificados contra objetivos limpios. Redis se reconstruye desde SQL.
La copia team autentica cada trabajo y evento del snapshot. Su inventario firmado registra trabajos, eventos, flujos, cursor,
envolturas, referencias y texto autenticado. Cada flujo debe ser 1..last_sequence y el cursor PostgreSQL no puede retrasarse.
La restauración repite y exige coincidencia. Los huecos entre cursores globales son válidos porque la identidad no es transaccional;
la secuencia por flujo sí es el contrato contiguo.
Si PLUGINS_DIR está fuera de DATA_DIR, se marca excluido y cualquier definición bloquea hasta respaldar también ese directorio.
Lo mismo se aplica a rutas heredadas; JSON simbólico, irregular o ilegible siempre bloquea.
Los trabajos duraderos están activos en ambos perfiles. Se bloquea mientras haya intento o Work activo, se validan cargas y cabezas, y se conserva SQL. Solo usa worker integrado; team usa worker externo y Redis solo para despertar y distribuir.
En producción guarda secretos en un gestor, archivos cifrados fuera del host y prueba restauraciones limpias. El inventario es una comprobación previa, no un bloqueo ni prueba de todos los recursos externos.
Comandos de copia firmada y cifrada
La barrera recovery-check se ejecuta antes de crear la copia. Los ejemplos usan libre-webui global y el subcomando libre-webui backup. Sustitúyelo por npx --yes libre-webui@latest o, desde código, compila y usa
npm run recovery:backup --. La imagen expone /usr/local/bin/libre-webui. Team exige pg_dump y pg_restore de PostgreSQL 16,
incluidos en imagen y fórmula Homebrew; instálalos explícitamente para npm/npx.
Genera la clave de archivo AES-256-GCM custodiada por el operador y el par de claves de firma Ed25519 en un directorio privado. Después, traslada las claves privadas a un almacenamiento protegido fuera del host:
install -d -m 0700 /absolute/private/libre-backup-keys
libre-webui backup keygen \
--directory /absolute/private/libre-backup-keys
Crea y verifica un archivo solo en reposo:
libre-webui backup create \
--offline \
--data-dir /absolute/path/to/libre-data \
--output /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
libre-webui backup verify \
--archive /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
Previsualiza y aplica solo a un destino nuevo vacío:
libre-webui backup restore-preflight \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-apply \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-verify \
--target /absolute/restore/libre-data
Para team, detén réplicas y workers y conserva cargado PostgreSQL/S3/keyring:
libre-webui backup create-team \
--offline \
--output /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
Carga una base y bucket versionado vacíos. La previsualización prueba que están vacíos; aplicar restaura y verifica PostgreSQL, S3 y PGVector y escribe configuración privada:
libre-webui backup restore-team-preflight \
--archive /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-team-apply \
--archive /absolute/backups/libre-team.lwbackup \
--configuration-output /absolute/restore/libre-team-config \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
Nunca dirijas una restauración a la base de datos de origen, al bucket de origen,
a un directorio de datos existente ni a un directorio de configuración que
contenga archivos. Conserva la clave pública de firma junto al procedimiento de
restauración; poseer solo el archivo y la clave pública no permite descifrar la
carga.
Si rollback queda incompleto, considera ambos objetivos sucios: limpia PostgreSQL y todas las versiones y marcadores bajo el prefijo S3,
y repite restore-team-preflight antes de reintentar.
Simulacros programados y verificados
Una copia nunca restaurada es esperanza, no recuperación. El simulacro ejecuta todo sin caída ni operador:
- Prepara una copia en reposo: SQLite mediante API online y archivos físicamente; espera a que no haya trabajos activos.
- Crea un archivo firmado y cifrado AES-256-GCM con claves efímeras y el inventario completo.
- Verifica, restaura en destino aislado y vuelve a verificar.
- Registra duración como RTO y separación entre éxitos como límite de RPO, y elimina todo. No conserva copias ni claves.
Activa RECOVERY_DRILL_INTERVAL_HOURS (por ejemplo 24). Un lease evita duplicados. Sistema muestra historial y «Ejecutar ahora»
mediante GET /api/recovery/drills y POST /api/recovery/drills/run. Los fallos desatendidos alertan a cada administrador y webhooks;
los manuales informan directamente. RECOVERY_DRILL_HISTORY conserva 60 entradas de forma predeterminada.
Los simulacros cubren solo SQLite. Team conserva backup create-team y su ensayo sigue siendo un paso manual.