Copia de seguridad y restauración
Dos cosas distintas, para dos accidentes distintos.
| Paquete cifrado | Copia de seguridad local programada | |
|---|---|---|
| Qué contiene | La configuración: monitores y sus credenciales, reglas, canales, páginas de estado, cuentas, tokens. | Toda la base de datos, como un archivo, más secret.key. |
| Dónde va | Donde tú lo pongas — está cifrado con una frase de paso que eliges. | /data/backups/, dentro del mismo volumen. |
| De qué te salva | Un servidor perdido, un traslado a hardware nuevo, una instalación limpia. | El cambio que lamentas diez minutos después, una actualización que salió mal. |
| Qué no contiene | Historial de métricas, estado e historial de alertas, el registro de auditoría, sesiones. | Historial de métricas (vm/). |
Ninguno sustituye un archivo de todo el volumen si también quieres recuperar las gráficas; eso está al final de esta página.
El paquete cifrado
Sección titulada «El paquete cifrado»Settings → Backup → Download the bundle. Elige una frase de paso de al menos 16 caracteres — tres palabras bastan — y confírmala. El archivo que se descarga es JSON plano con un cuerpo cifrado:
{ "format": "dumbmonit-backup", "version": 1, "created_at": "2026-09-22 19:04:11", "source_version": "0.1.0-alpha.3", "summary": { "targets": 12, "channels": 2, "rules": 41 }, "kdf": { "algorithm": "argon2id", "salt": "…", "m_cost": 32768, "t_cost": 3, "p_cost": 1 }, "cipher": "aes-256-gcm", "payload": "…"}La cabecera se mantiene legible para que puedas saber qué es un archivo
antes de escribir nada. Todo lo demás — direcciones incluidas — está
dentro de payload, cifrado con AES-256-GCM bajo una clave derivada de
tu frase de paso por Argon2id. No hay recuperación: un paquete cuya
frase de paso se pierde se pierde.
Qué contiene
Sección titulada «Qué contiene»| Sección | Contenido |
|---|---|
targets | Monitores: nombre, tipo, dirección, intervalo, opciones, padre, agente relay, y la credencial. |
rules | Reglas de alerta, incluidas las integradas que hayas reajustado o desactivado. |
rule_overrides | Umbrales y exclusiones por monitor. |
channels | Canales de notificación, sus ajustes, su política por canal y sus secretos. |
notify_policy | La política de notificación global (agrupamiento, límite por hora, flapping, URL pública). |
silences | Ventanas de mantenimiento. |
status_pages | Páginas de estado públicas y los servicios que lista cada una. |
incidents | Incidentes y anuncios de mantenimiento, con sus actualizaciones. |
users | Cuentas: nombre de usuario, nombre mostrado, rol, enlace SSO, activado o no. |
agent_tokens | Tokens de inscripción de agente, como hashes. Los agentes instalados siguen enviando tras una restauración. |
api_tokens | Tokens de API, como hashes. Los tokens existentes siguen funcionando. |
push_monitors | Tokens de heartbeat, así las URL que ya llaman tus tareas cron siguen siendo las mismas. |
Los monitores se emparejan por tipo + dirección, que es también la clave única de la tabla: importar el mismo paquete dos veces nunca crea una segunda copia de nada.
Contraseñas de cuenta
Sección titulada «Contraseñas de cuenta»Por defecto las cuentas se exportan sin su hash de contraseña, secreto TOTP ni códigos de recuperación. Las cuentas restauradas entonces existen con el nombre y rol correctos, pero nadie puede iniciar sesión con ellas hasta que un administrador defina una contraseña — o hasta que inicien sesión por SSO, lo cual no necesita nada del paquete.
Activa Include account passwords and 2FA secrets cuando estás trasladando una instancia en lugar de copiar su configuración. Un hash Argon2 en un archivo que viaja puede atacarse sin conexión durante todo el tiempo que el atacante quiera; lo por defecto es lo seguro.
Qué no contiene
Sección titulada «Qué no contiene»El historial de métricas (vive en VictoriaMetrics, no en la base de datos), el estado e historial de alertas, las referencias de anomalía, el registro de auditoría, las sesiones abiertas, el registro y última visita de los agentes, y las cachés de sonda de los paneles Proxmox y Synology. Son observaciones, no ajustes: vuelven por su cuenta.
Y no el secreto de la instancia. Ese es el punto: el paquete lleva
sus secretos recifrados bajo tu frase de paso precisamente para que se
pueda restaurar en algún sitio que nunca ha visto secret.key.
Restaurar sobre una instancia nueva
Sección titulada «Restaurar sobre una instancia nueva»- Inicia el contenedor nuevo y crea la primera cuenta de administrador
en
/setup, con el código de configuración impreso en sus logs. Esa cuenta es tuya; la restauración no la tocará. - Settings → Backup → Restore a bundle. Elige el archivo, escribe la frase de paso, y pulsa Check this backup.
- Lee el informe. Indica, sección por sección, qué se crearía, qué se actualizaría porque difiere de lo que ya hay, y qué ya es idéntico — más una nota para cualquier cosa que no pudo ubicar, como una regla que apuntaba a un monitor que el paquete no contiene.
- Pulsa Restore for real.
Tres reglas que la restauración nunca rompe:
- Nada se elimina nunca. Una restauración hace que exista lo que describe el paquete; cualquier cosa que la instancia tenga además permanece.
- Nada se duplica nunca. Cada elemento se empareja por su clave
natural — tipo + dirección para un monitor,
uidpara una regla, nombre para un canal, slug para una página de estado. Restaurar el mismo paquete dos veces reporta todo como ya idéntico y no escribe nada. - Las cuentas existentes se dejan en paz. Una cuenta cuyo nombre de usuario ya está aquí se omite, nunca se sobrescribe: un archivo no debe poder cambiar el rol o la contraseña del administrador que ejecuta la restauración.
Una simulación no es una simulación de la restauración, es la restauración, ejecutada dentro de una transacción que se revierte al final. El informe no puede estar equivocado sobre lo que haría aplicarla.
Un paquete escrito por un DumbMonit más reciente se rechaza con una frase que lo indica — actualiza primero, luego restaura. Un paquete que ha sido modificado, o cuya frase de paso es incorrecta, también se rechaza: AES-GCM no puede distinguir los dos casos, y tampoco puede el mensaje.
Desde la línea de comandos
Sección titulada «Desde la línea de comandos»Ambas rutas necesitan una sesión de administrador, no un token de API: un token vive en un script, y un script no tiene por qué exportar cada credencial de la instancia.
# Iniciar sesióncurl -s -c jar -X POST https://localhost:8080/api/auth/login \ -H 'content-type: application/json' -H 'X-Requested-With: DumbMonit' \ -d '{"username":"admin","password":"…"}'
# Exportarcurl -s -b jar -X POST https://localhost:8080/api/backup \ -H 'content-type: application/json' -H 'X-Requested-With: DumbMonit' \ -d '{"passphrase":"three words are enough"}' -o backup.json
# Simulación, luego aplicarjq -n --slurpfile b backup.json \ '{bundle: $b[0], passphrase: "three words are enough", apply: false}' > restore.jsoncurl -s -b jar -X POST https://localhost:8080/api/backup/restore \ -H 'content-type: application/json' -H 'X-Requested-With: DumbMonit' \ -d @restore.json | jqCopias de seguridad locales programadas
Sección titulada «Copias de seguridad locales programadas»DumbMonit escribe una copia de su propia base de datos de forma
programada, por defecto una vez al día, conservando las últimas
siete, en /data/backups/:
/data/backups/dumbmonit-20260922-030000.db/data/backups/dumbmonit-20260922-030000.keyEl archivo .db se produce con VACUUM INTO de SQLite: una copia en
línea y consistente escrita mientras el servidor sigue funcionando, no
una copia de archivo que podría capturar la base de datos a mitad de
una escritura. sqlite3 la abre tal cual, sin ningún journal que
reproducir. El .key a su lado es la copia de secret.key — juntos, el
par basta para reconstruir la instancia.
Viven en el mismo volumen que la base de datos, así que deshacen un error, no un disco perdido. Cópialos fuera de la máquina si quieres más que eso.
Ajustes
Sección titulada «Ajustes»| Variable | Por defecto | Rol |
|---|---|---|
DUMBMONIT_BACKUP_ENABLED | 1 | 0, false, no u off para dejar de escribir copias programadas. |
DUMBMONIT_BACKUP_DIR | <directorio de datos>/backups | Dónde se escriben. Apúntalo a un segundo volumen para sobrevivir a la pérdida del primero. |
DUMBMONIT_BACKUP_INTERVAL_HOURS | 24 | Horas entre dos copias de seguridad. La primera ocurre un intervalo después del arranque, no al arrancar. |
DUMBMONIT_BACKUP_KEEP | 7 | Cuántas se conservan. Las más antiguas se eliminan, con su .key. |
Nada más en el directorio se toca nunca: solo se rotan los archivos
llamados dumbmonit-<timestamp>.db y su .key.
Cuando el secreto de la instancia viene de DUMBMONIT_SECRET no hay
ningún archivo que copiar, y no se escribe ninguno — guarda ese valor en
tu gestor de contraseñas en su lugar. La sección Backup indica en cuál
de los dos casos estás.
Saber que se ejecutó
Sección titulada «Saber que se ejecutó»Cada ejecución publica tres series:
| Métrica | Significado |
|---|---|
dumbmonit_instance_backup_last_success_seconds | Timestamp Unix de la última copia de seguridad exitosa. Un intento fallido nunca la refresca. |
dumbmonit_instance_backup_last_status | 1 si el último intento tuvo éxito, 0 si falló. |
dumbmonit_instance_backup_size_bytes | Tamaño del último archivo escrito. |
La regla integrada DumbMonit backup did not run
(instance_backup_missing) se activa cuando el último éxito tiene más
de dos días — una noche perdida puede ser un reinicio, dos es un
problema. La serie solo existe una vez escrita una primera copia de
seguridad, así que una instancia con la programación desactivada nunca
recibe el aviso.
Settings → Backup muestra lo mismo sin MetricsQL: la última ejecución y si tuvo éxito, los archivos conservados y su tamaño, y Back up now para escribir una de inmediato.
Restaurar una
Sección titulada «Restaurar una»Detén el stack, pon el archivo de vuelta bajo el nombre de la base de datos, y restaura la clave junto a él:
docker compose stopdocker run --rm -v dumbmonit-data:/data alpine sh -c ' cp /data/backups/dumbmonit-20260922-030000.db /data/dumbmonit.db && cp /data/backups/dumbmonit-20260922-030000.key /data/secret.key && rm -f /data/dumbmonit.db-wal /data/dumbmonit.db-shm'docker compose startEliminar los archivos -wal y -shm importa: pertenecen a la base de
datos que acabas de reemplazar, y SQLite intentaría aplicarlos a la
nueva.
Para leer una copia de seguridad sin restaurarla, cópiala fuera y ábrela
con sqlite3:
docker run --rm -v dumbmonit-data:/data -v "$PWD:/out" alpine \ cp /data/backups/dumbmonit-20260922-030000.db /out/sqlite3 dumbmonit-20260922-030000.db 'SELECT name, kind, address FROM targets;'Las credenciales de ese archivo permanecen ilegibles sin el
secret.key correspondiente.
Archivar todo el volumen
Sección titulada «Archivar todo el volumen»La única forma de conservar también las gráficas. Un volumen con
nombre, dumbmonit-data, contiene todo: la base de datos, el secreto,
las copias de seguridad locales y los datos de VictoriaMetrics.
docker compose stopdocker run --rm -v dumbmonit-data:/data -v "$PWD:/backup" alpine \ tar czf /backup/dumbmonit-data.tgz -C /data .docker compose startPara restaurar, crea el volumen, extrae el archivo comprimido en él de
la misma forma, y luego docker compose up -d.
Si el espacio importa, --exclude=./vm mantiene el archivo pequeño: la
base de datos y el secreto son la configuración, vm/ es solo el
historial.
Qué hacer antes de una actualización
Sección titulada «Qué hacer antes de una actualización»- Settings → Backup → Back up now — treinta segundos, e incluye el secreto.
- Descarga también un paquete si la actualización es grande, o si te mudas a otra máquina.
docker compose pull && docker compose up -d. Las migraciones se ejecutan al arrancar.
Si algo sale mal, restaura la copia de seguridad local y arranca la etiqueta de imagen anterior.