Saltar al contenido principal

Esquema de Base de Datos

Este documento describe el esquema de base de datos SQLite utilizado por duplistatus para almacenar datos de operaciones de copia de seguridad.

Ubicación de la Base de Datos​

La base de datos se almacena en el directorio de datos de la aplicación:

  • Ubicación Predeterminada: /app/data/backups.db
  • Volumen Docker: duplistatus_data:/app/data
  • Nombre de Archivo: backups.db

Sistema de Migración de Base de Datos​

duplistatus utiliza un sistema de migración automatizado para gestionar cambios en el esquema de la base de datos entre versiones.

Historial de Versiones de Migración​

Las siguientes son versiones de migración históricas que llevaron la base de datos a su estado actual:

  • Esquema v1.0 (Aplicación v0.6.x y anteriores): Esquema de base de datos inicial con tablas de servidores y copias de seguridad
  • Esquema v2.0 (Aplicación v0.7.x): Se agregaron columnas faltantes y tabla de configuraciones
  • Esquema v3.0 (Aplicación v0.7.x): Se renombró la tabla de servidores, se agregó columna server_url
  • Esquema v3.1 (Aplicación v0.8.x): Se mejoraron los campos de datos de copia de seguridad, se agregó columna server_password
  • Esquema v4.0 (Aplicación v0.9.x / v1.0.x): Se agregaron tablas de Control de Acceso de Usuarios (usuarios, sesiones, registro de auditoría)
  • Esquema v4.1 (Aplicación v1.5.x): Se agregaron api_keys y claves de configuración predeterminadas para autenticación opcional por clave API, listas de permitidos de IP y límites de subida
  • Esquema v4.2 (Aplicación v1.5.x): Se agregó daily_summary_deliveries libro mayor y configuración daily_summary predeterminada para notificaciones opcionales de resumen diario

La versión actual de la aplicación (v1.5.x) utiliza Esquema v4.2 como la versión de esquema de base de datos más reciente.

Proceso de Migración​

  1. Copia de Seguridad Automática: Crea copia de seguridad antes de la migración
  2. Actualización de Esquema: Actualiza la estructura de la base de datos
  3. Migración de Datos: Preserva los datos existentes
  4. Verificación: Confirma la migración exitosa

Tablas​

Tabla de Servidores​

Almacena información sobre los servidores Duplicati que se están monitoreando.

Campos​

CampoTipoDescripción
idTEXT PRIMARY KEYIdentificador único del servidor
nameTEXT NOT NULLNombre del servidor desde Duplicati
server_urlTEXTURL del servidor Duplicati
aliasTEXTNombre amigable definido por el usuario
noteTEXTNotas/descripción definidas por el usuario
server_passwordTEXTContraseña del servidor para autenticación
created_atDATETIMEMarca de tiempo de creación del servidor

Tabla de Copias de seguridad​

Almacena datos de operaciones de copia de seguridad recibidos de servidores Duplicati.

Campos clave​

CampoTipoDescripción
idTEXT PRIMARY KEYIdentificador único de copia de seguridad
server_idTEXT NOT NULLReferencia a la tabla de servidores
backup_nameTEXT NOT NULLNombre del trabajo de copia de seguridad
backup_idTEXT NOT NULLID de copia de seguridad de Duplicati
dateDATETIME NOT NULLHora de ejecución de la copia de seguridad
statusTEXT NOT NULLEstado de copia de seguridad (Éxito, Advertencia, Error, Fatal)
duration_secondsINTEGER NOT NULLDuración en segundos
sizeINTEGERTamaño de archivos de origen
uploaded_sizeINTEGERTamaño de datos subidos
examined_filesINTEGERNúmero de archivos examinados
warningsINTEGERNúmero de advertencias
errorsINTEGERNúmero de errores
created_atDATETIMEMarca de tiempo de creación del registro

Matrices de Mensajes (Almacenamiento JSON)​

FieldTypeDescripción
messages_arrayTEXTArray JSON de Mensajes de registro
warnings_arrayTEXTArray JSON de Mensajes de Advertencia
errors_arrayTEXTArray JSON de mensajes de error
available_backupsTEXTArray JSON de versiones de copia de seguridad disponibles

Campos de Operación de Archivos​

FieldTypeDescription
examined_filesINTEGERArchivos examinados durante la copia de seguridad
opened_filesINTEGERArchivos abiertos para copia de seguridad
added_filesINTEGERArchivos nuevos añadidos a la copia de seguridad
modified_filesINTEGERArchivos modificados en copia de seguridad
deleted_filesINTEGERArchivos eliminados de la copia de seguridad
deleted_foldersINTEGERCarpetas eliminadas de la copia de seguridad
added_foldersINTEGERCarpetas añadidas a copia de seguridad
modified_foldersINTEGERCarpetas modificadas en copia de seguridad
not_processed_filesINTEGERArchivos no procesados
too_large_filesINTEGERArchivos demasiado grandes para procesar
files_with_errorINTEGERArchivos con errores
added_symlinksINTEGEREnlaces simbólicos añadidos
modified_symlinksINTEGEREnlaces simbólicos modificados
deleted_symlinksINTEGEREnlaces simbólicos eliminados

Campos de Tamaño de Archivo​

CampoTipoDescripción
size_of_examined_filesINTEGERTamaño de Archivo de archivos examinados durante la copia de seguridad
size_of_opened_filesINTEGERTamaño de Archivo de archivos abiertos para la copia de seguridad
size_of_added_filesINTEGERTamaño de Archivo de nuevos archivos añadidos a la copia de seguridad
size_of_modified_filesINTEGERTamaño de Archivo de archivos modificados en la copia de seguridad

Campos de Estado de Operación​

CampoTipoDescripción
parsed_resultTEXT NOT NULLResultado de operación analizado
main_operationTEXT NOT NULLTipo de operación principal
interruptedBOOLEANSi la copia de seguridad fue interrumpida
partial_backupBOOLEANSi la copia de seguridad fue parcial
dryrunBOOLEANSi la copia de seguridad fue una ejecución de prueba
versionTEXTVersión de duplicati utilizada
begin_timeDATETIME NOT NULLHora de inicio de la copia de seguridad
end_timeDATETIME NOT NULLHora de finalización de la copia de seguridad
warnings_actual_lengthINTEGERRecuento real de advertencias
errors_actual_lengthINTEGERRecuento real de errores
messages_actual_lengthINTEGERRecuento real de mensajes

Campos de Estadísticas de Backend​

CampoTipoDescripción
bytes_downloadedINTEGERBytes descargados del destino
known_file_sizeINTEGERTamaño de Archivo conocido en el destino
last_backup_dateDATETIMEFecha de última copia de seguridad en el destino
backup_list_countINTEGERNúmero de versiones de copia de seguridad
reported_quota_errorBOOLEANError de cuota reportado
reported_quota_warningBOOLEANAdvertencia de cuota reportada
backend_main_operationTEXTOperación principal del backend
backend_parsed_resultTEXTResultado analizado del backend
backend_interruptedBOOLEANOperación del backend interrumpida
backend_versionTEXTVersión del backend
backend_begin_timeDATETIMEHora de inicio de la operación del backend
backend_durationTEXTDuración de la operación del backend
backend_warnings_actual_lengthINTEGERRecuento de advertencias del backend
backend_errors_actual_lengthINTEGERRecuento de errores del backend

Tabla de Configuraciones​

Almacena la configuración de la aplicación.

Campos​

CampoTipoDescripción
keyTEXT PRIMARY KEY NOT NULLClave de configuración
valueTEXTValor de configuración (JSON)

Claves de Configuración Comunes​

  • email_config: Configuración de correo electrónico
  • ntfy_config: Configuración de notificaciones NTFY
  • overdue_tolerance: Configuración de tolerancia de copia de seguridad vencida
  • notification_templates: Plantillas de mensajes de notificación
  • daily_summary: Modo de Resumen Diario, horario, zona horaria, URL del panel público opcional y anulación opcional de Destinatario SMTP (smtpRecipient; vacío utiliza Configuración de correo electrónico)
  • cron_service: Horarios de tareas Cron, incluyendo daily-summary-dispatch (minute hour * * * de daily_summary.utcTime)
  • audit_retention_days: Retención de Registro de Auditoría (predeterminada: 90 días)

Tabla de Versión de Base de Datos​

Realiza un seguimiento de la versión del esquema de la base de datos para fines de migración.

Campos​

CampoTipoDescripción
versionTEXT PRIMARY KEYVersión de base de datos
applied_atDATETIMECuándo se aplicó la migración

Tabla de Usuarios​

Almacena información de cuentas de usuario para autenticación y control de acceso.

Campos​

CampoTipoDescripción
idTEXT PRIMARY KEYIdentificador único de usuario
usernameTEXT UNIQUE NOT NULLNombre de usuario para inicio de sesión
password_hashTEXT NOT NULLContraseña con hash Bcrypt
is_adminBOOLEAN NOT NULLSi el usuario tiene privilegios de administrador
must_change_passwordBOOLEANSi se requiere cambio de contraseña
created_atDATETIMEMarca de tiempo de creación de cuenta
updated_atDATETIMEMarca de tiempo de última actualización
last_login_atDATETIMEMarca de tiempo del último inicio de sesión exitoso
last_login_ipTEXTDirección IP del último inicio de sesión
failed_login_attemptsINTEGERRecuento de intentos de inicio de sesión fallidos
locked_untilDATETIMEExpiración del bloqueo de cuenta (si está bloqueado)

Tabla de Sesiones​

Almacena datos de sesión de usuario para autenticación y seguridad.

Campos​

CampoTipoDescripción
idTEXT PRIMARY KEYIdentificador de sesión
user_idTEXTReferencia a la tabla de usuarios (nula para sesiones no autenticadas)
created_atDATETIMEMarca de tiempo de creación de sesión
last_accessedDATETIMEMarca de tiempo de último acceso
expires_atDATETIME NOT NULLMarca de tiempo de expiración de sesión
ip_addressTEXTDirección IP de origen de sesión
user_agentTEXTCadena de agente de usuario
csrf_tokenTEXTToken CSRF para la sesión
csrf_expires_atDATETIMEExpiración del token CSRF

Tabla de Registro de auditoría​

Almacena el registro de auditoría de acciones de usuario y eventos del sistema.

Campos​

CampoTipoDescripción
idINTEGER PRIMARY KEY AUTOINCREMENTIdentificador único de entrada de registro de auditoría
timestampDATETIMEMarca de tiempo de evento
user_idTEXTReferencia a la tabla de usuarios (nula)
usernameTEXTNombre de usuario en el momento de la acción
actionTEXT NOT NULLAcción realizada
categoryTEXT NOT NULLCategoría de acción (p. ej., 'autenticación', 'configuración', 'copia de seguridad')
target_typeTEXTTipo de destino (p. ej., 'servidor', 'copia de seguridad', 'usuario')
target_idTEXTIdentificador de destino
detailsTEXTDetalles adicionales (JSON)
ip_addressTEXTDirección IP del solicitante
user_agentTEXTCadena de agente de usuario
statusTEXT NOT NULLEstado de la acción ('éxito', 'error', 'error')
error_messageTEXTMensaje de error si la acción falló

Tabla de claves de API​

Almacena claves de API con hash para las API HTTP externas. El secreto en texto plano se muestra una sola vez en la creación y nunca se almacena.

Campos​

CampoTipoDescripción
idTEXT PRIMARY KEYIdentificador único de clave
nameTEXT NOT NULLNombre para mostrar
key_hashTEXT UNIQUEHash SHA-256 del secreto
key_prefixTEXTPrimeros cuatro caracteres del secreto (para huellas dactilares)
key_suffixTEXTÚltimos cuatro caracteres del secreto (para huellas dactilares)
scopeTEXT NOT NULLupload o read
descriptionTEXTDescripción opcional
enabledINTEGER1 cuando la clave está activa
created_atDATETIMEMarca de tiempo de creación
created_byTEXTId de usuario del administrador que creó la clave
expires_atDATETIMEExpiración opcional
last_used_atDATETIMEÚltimo uso exitoso
usage_countINTEGERRecuento de usos exitosos

Claves de configuración relacionadas en la tabla configurations: external_api_require_api_key, ip_trusted_proxies, admin_ip_allowlist, external_api_ip_allowlist, upload_limits.

Tabla de entregas de Resumen Diario​

Libro mayor por canal para la entrega de correo electrónico de Resumen Diario. Las filas heredadas pueden incluir un canal ntfy de versiones anteriores. Cada ocurrencia programada (o envío manual único) tiene como máximo una fila por canal. Las cargas útiles procesadas se almacenan antes del envío para que los reintentos mantengan la misma instantánea. Las filas más antiguas de 30 días se eliminan.

Si el proceso muere después de que un proveedor acepta un mensaje pero antes de que se registre el éxito, ese canal puede reintentarse (al menos una vez).

Campos​

CampoTipoDescripción
idTEXT PRIMARY KEYIdentificador de entrega único
occurrence_keyTEXT NOT NULLClave programada scheduled:UTC:{date}:{HH:mm} o manual:{uuid}
channelTEXT NOT NULLemail o ntfy
triggerTEXT NOT NULLscheduled, manual, o retry
summary_dateTEXT NOT NULLFecha de calendario local para la instantánea
time_zoneTEXT NOT NULLZona horaria IANA guardada
payload_jsonTEXTAsunto procesado, campos HTML, texto y NTFY
stateTEXT NOT NULLpending, sending, sent, o failed
attempt_countINTEGERIntentos de entrega
next_retry_atDATETIMECuándo un canal fallido puede reclamarse nuevamente
lease_expires_atDATETIMEArrendamiento de reclamación; un arrendamiento obsoleto puede recuperarse
errorTEXTÚltimo error, si existe
created_atDATETIMEMarca de tiempo de creación de fila
updated_atDATETIMEMarca de tiempo de última actualización
sent_atDATETIMEMarca de tiempo de éxito

Un índice único en (occurrence_key, channel) previene envíos duplicados de la misma ocurrencia en el mismo canal.

Gestión de sesiones​

Almacenamiento de sesiones respaldado por base de datos​

Las sesiones se almacenan en la base de datos con respaldo en memoria:

  • Almacenamiento principal: Tabla de sesiones respaldada por base de datos
  • Respaldo: Almacenamiento en memoria (soporte heredado o casos de error)
  • ID de sesión: Cadena aleatoria criptográficamente segura
  • Expiración: Tiempo de espera de sesión configurable
  • Protección CSRF: Protección contra falsificación de solicitudes entre sitios
  • Limpieza automática: Las sesiones expiradas se eliminan automáticamente

Puntos finales de API de sesión​

  • POST /api/session: Crear nueva sesión
  • GET /api/session: Validar sesión existente
  • DELETE /api/session: Destruir sesión
  • GET /api/csrf: Obtener token CSRF

Índices​

La base de datos incluye varios índices para un rendimiento óptimo de consultas:

  • Claves principales: Todos los tablas tienen índices de clave principal
  • Claves externas: Referencias de servidor en tabla de copias de seguridad, referencias de usuario en sesiones y registro de auditoría
  • Optimización de consultas: Índices en campos consultados frecuentemente
  • Índices de fecha: Índices en campos de fecha para consultas basadas en tiempo
  • Índices de usuario: Índice de nombre de usuario para búsquedas rápidas de usuario
  • Índices de sesión: Índices de expiración e id_usuario para gestión de sesiones
  • Índices de auditoría: Índices de marca de tiempo, id_usuario, acción, categoría y estado para consultas de auditoría
  • Índices de clave de API: Hash único, más búsquedas de ámbito/habilitado para autenticación

Relaciones​

  • Servidores → Copias de seguridad: Relación uno a muchos
  • Usuarios → Sesiones: Relación uno a muchos (las sesiones pueden existir sin usuarios)
  • Usuarios → Registro de auditoría: Relación uno a muchos (las entradas de auditoría pueden existir sin usuarios)
  • Usuarios → Claves de API: Relación uno a muchos a través de created_by (las claves permanecen después de que se elimina el usuario)
  • Copias de seguridad → Mensajes: Matrices JSON incrustadas
  • Configuraciones: Almacenamiento de clave-valor

Tipos de datos​

  • TEXT: Datos de cadena, matrices JSON
  • INTEGER: Datos numéricos, recuentos de archivos, tamaños
  • REAL: Números de punto flotante, duraciones
  • DATETIME: Datos de marca de tiempo
  • BOOLEAN: Valores verdadero/falso

Estados de Copia de seguridad​

  • Éxito: Copia de seguridad completada exitosamente
  • Advertencia: Copia de seguridad completada con advertencias
  • Error: Copia de seguridad completada con errores
  • Fatal: Copia de seguridad falló fatalmente

Consultas Comunes​

Obtener la Última Copia de seguridad para un Servidor​

SELECT * FROM backups
WHERE server_id = ?
ORDER BY date DESC
LIMIT 1;

Obtener Todas las Copias de seguridad para un Servidor​

SELECT * FROM backups
WHERE server_id = ?
ORDER BY date DESC;

Obtener Resumen del Servidor​

SELECT
s.name,
s.alias,
COUNT(b.id) as backup_count,
MAX(b.date) as last_backup,
b.status as last_status
FROM servers s
LEFT JOIN backups b ON s.id = b.server_id
GROUP BY s.id;

Obtener Resumen General​

SELECT
COUNT(DISTINCT s.id) as total_servers,
COUNT(b.id) as total_backups_runs,
COUNT(DISTINCT s.id || ':' || b.backup_name) as total_backups,
COALESCE(SUM(b.uploaded_size), 0) as total_uploaded_size,
(
SELECT COALESCE(SUM(b2.known_file_size), 0)
FROM backups b2
INNER JOIN (
SELECT server_id, MAX(date) as max_date
FROM backups
GROUP BY server_id
) latest ON b2.server_id = latest.server_id AND b2.date = latest.max_date
) as total_storage_used,
(
SELECT COALESCE(SUM(b2.size_of_examined_files), 0)
FROM backups b2
INNER JOIN (
SELECT server_id, MAX(date) as max_date
FROM backups
GROUP BY server_id
) latest ON b2.server_id = latest.server_id AND b2.date = latest.max_date
) as total_backuped_size
FROM servers s
LEFT JOIN backups b ON b.server_id = s.id;

Limpieza de Base de Datos​

-- Delete old backups (older than 30 days)
DELETE FROM backups
WHERE date < datetime('now', '-30 days');

-- Delete servers with no backups
DELETE FROM servers
WHERE id NOT IN (SELECT DISTINCT server_id FROM backups);

Asignación de JSON a Base de Datos​

Asignación de Cuerpo de Solicitud de API a Columnas de Base de Datos​

Cuándo duplicati envía datos de copia de seguridad a través de HTTP POST, la estructura JSON se asigna a columnas de base de datos:

{
"Data": {
"ExaminedFiles": 15399, // → examined_files
"OpenedFiles": 1861, // → opened_files
"AddedFiles": 1861, // → added_files
"SizeOfExaminedFiles": 11086692615, // → size_of_examined_files
"SizeOfOpenedFiles": 13450481, // → size_of_opened_files
"SizeOfAddedFiles": 13450481, // → size_of_added_files
"SizeOfModifiedFiles": 0, // → size_of_modified_files
"ParsedResult": "Success", // → status
"BeginTime": "2025-04-21T23:45:46.9712217Z", // → begin_time and date
"Duration": "00:00:51.3856057", // → duration_seconds (calculated)
"WarningsActualLength": 0, // → warnings_actual_length
"ErrorsActualLength": 0 // → errors_actual_length
},
"Extra": {
"machine-id": "66f5ffc7ff474a73a3c9cba4ac7bfb65", // → server_id
"machine-name": "WSJ-SER5", // → server name
"backup-name": "WSJ-SER5 Local files", // → backup_name
"backup-id": "DB-2" // → backup_id
}
}

Nota: El campo size en la tabla de copias de seguridad almacena SizeOfExaminedFiles y uploaded_size almacena el tamaño real subido/transferido de la operación de copia de seguridad.