Un análisis técnico basado en BorgBackup para entornos Debian/Ubuntu

Autor: Arcadio Ortega Reinoso
Versión del sistema: 2.1.0
Fecha: Julio 2026
Plataforma objetivo: Debian 11+ / Ubuntu 22.04+ (x86_64)


Puedes encontrarlo en: BorgShield


Fortalezas Diferenciales

Valor Diferencial Claro: La inclusión de 23 tipos de metadatos
(repositorios git, dconf, claves GPG, snaps, flatpaks, etc.) resuelve el
problema de tener los archivos pero no saber cómo reconstruir el entorno.
No es solo "tus datos están a salvo", es "sabemos exactamente qué tenías
y cómo volver a dejarlo igual".

Restauración Semántica: test-restore va más allá de borg check.
Mientras que otras herramientas solo verifican checksums (integridad
técnica), nosotros verificamos si los datos son realmente legibles y útiles
(integridad semántica): ¿el SQL de las BBDD se puede leer? ¿los paquetes
están en formato válido? ¿las rutas esenciales existen? ¿los gzips no
están corruptos?

Asistente Guiado: restore-full y restore-dry-run forman un sistema
de dos velocidades: simular antes de ejecutar, y guiar paso a paso durante
la ejecución real. Esto reduce significativamente el "pánico" durante un
desastre real, guiando incluso en la reinstalación de paquetes y fuentes APT.


Resumen

Este documento presenta el diseño, la implementación y la evaluación de
backup.sh, un sistema de backup para Linux orientado a disco externo
local. El sistema se basa en BorgBackup como motor de almacenamiento
deduplicado, cifrado y comprimido. Se analizan las alternativas existentes
(rsync, rsnapshot, restic), se justifican las decisiones de diseño y se
presentan proyecciones de rendimiento basadas en métricas obtenidas de un
sistema real con ~360 GB de datos, ~3200 paquetes instalados y ~460 paquetes
instalados manualmente.

Los resultados muestran que BorgBackup reduce el espacio de almacenamiento
del backup completo a ~160 GB (55% de compresión con deduplicación), los
backups incrementales se completan en 3-8 minutos, y el sistema permite
restauración granular por archivo, por directorio o completa del sistema
operativo con una guía interactiva paso a paso.


1. Ventaja Diferencial

1.1 Matriz de diferenciación

Capacidad rsync rsnapshot restic duplicity timeshift Borg CLI backup.sh
Un solo archivo
Sin archivos de configuración externos N/A
Dumps BBDD automáticos
Test-restore virtual
Simulación restauración
Metadatos de paquetes
Restauración guiada
Reporte de exclusiones
Mapa de repos git
Entornos de desarrollo
Inventario de VMs
Crontab-ready
Modo silencioso/sin prompts

Ninguna herramienta existente cubre más de 2 de estas 13 capacidades.

1.2 Lo que otros tienen y backup.sh no

Capacidad Herramienta Impacto
Backup multi-cloud nativo (S3, B2, Azure, GCP) restic backup.sh requiere rclone como capa adicional
Binario único sin dependencias restic backup.sh requiere bash + borg + rsync + python3
Archivos directamente accesibles sin extracción rsync backup.sh requiere borg extract o mount (FUSE)
Interfaz gráfica (GUI) timeshift, deja-dup backup.sh es solo CLI
Instantáneas de arranque (boot-time recovery) timeshift backup.sh requiere disco externo montado
Cifrado GPG interoperable duplicity backup.sh usa formato Borg (no portable sin Borg)
Verificación integrada post-backup restic (restic check) backup.sh requiere comando explícito check
Backups remotos vía SSH nativo rsync, Borg CLI backup.sh está diseñado para disco local

Conclusión: backup.sh sacrifica portabilidad cloud e interoperabilidad
a cambio de profundidad en metadatos, automatización de BBDD y restauración
guiada. Es la herramienta correcta para backup local a disco externo donde
se necesita recuperación completa del sistema, no para backup cloud.


2. Introducción y Planteamiento del Problema

2.1 El problema del backup en Linux

A día de hoy, hacer backups efectivos en Linux sigue siendo un desafío
técnico. Aunque existen numerosas herramientas, la mayoría adolece de al
menos uno de estos problemas:

  1. Ausencia de deduplicación: los backups completos duplican datos que no han cambiado, consumiendo espacio innecesario.
  2. Falta de verificación: sin checksums, no hay garantía de que los datos almacenados sean recuperables.
  3. Dependencia del sistema de archivos: los sistemas basados en hardlinks (rsnapshot, rsync + --link-dest) requieren soporte del FS subyacente, problemático en NTFS u otros formatos comunes en discos externos.
  4. Restauración compleja: recuperar un sistema completo desde cero requiere múltiples herramientas y conocimientos.
  5. Carencia de cifrado: los datos en disco externo viajan sin protección.

2.2 Requisitos del sistema

El sistema que nos ocupa presenta las siguientes características:

Métrica Valor
Distribución Ubuntu 22.04.5 LTS
Kernel 5.15.x
Paquetes totales ~3200
Paquetes manuales ~460
Datos en / ~360 GB
Disco de backup NTFS 1.9T (418 GB libres)

El objetivo es diseñar un sistema de backup que cumpla:

  • Eficiencia: backups rápidos que minimicen el espacio en disco.
  • Fiabilidad: verificación criptográfica de integridad.
  • Restaurabilidad: recuperación granular (archivo individual) y total (sistema completo desde una instalación limpia).
  • Operación autónoma: ejecución desatendida via cron, con notificación de errores.
  • Seguridad: cifrado de los datos en reposo.

3. Soluciones Existentes y sus Limitaciones

3.1 rsync con hardlinks (rsnapshot)

Mecanismo: rsync -aAX --link-dest=<anterior> + cp -al para crear
snapshots con hardlinks a archivos sin cambios.

Ventajas:

  • Los archivos son directamente accesibles (cada snapshot es un directorio).
  • Sin dependencias adicionales más allá de rsync.

Limitaciones:

  • Dependencia del FS: NTFS-3G soporta hardlinks, pero con significativa degradación de rendimiento. La creación de hardlinks en NTFS requiere operaciones de metadatos lentas.
  • Sin compresión: los archivos se almacenan tal cual, ocupando el 100% del espacio original.
  • Sin cifrado nativo: requiere capa adicional (gpg, encfs).
  • Sin verificación: no hay checksums de los datos almacenados.
  • Growth lineal: cada nuevo "full" copia todo aunque no haya cambios.

Proyección para nuestro sistema: Con ~360 GB de origen y rotación de 3
fulls, ocuparíamos ~1.1 TB en 12 meses. En un disco de 1.9 TB con 418 GB
libres, esto es inviable a largo plazo.

3.2 Restic

Mecanismo: repositorio chunk-based con deduplicación y cifrado,
similar a Borg pero con énfasis en almacenamiento en la nube.

Ventajas:

  • Excelente para backups remotos (S3, Backblaze, Azure).
  • Deduplicación y cifrado.
  • FUSE mount.

Limitaciones:

  • Compresión menos eficiente que Borg en escenarios locales (no usa zstd).
  • Menor madurez en el ecosistema (Borg tiene 15+ años).
  • Montaje FUSE menos estable.

3.3 Timeshift (modo rsync)

Mecanismo: rsync con hardlinks + interfaz gráfica.

Ventajas:

  • Interfaz amigable.
  • Bueno para snapshots del sistema.

Limitaciones:

  • No cifra.
  • No comprime.
  • No tiene verificación.
  • Depende de hardlinks.
  • Orientado a restauración del sistema, no de archivos de usuario.

3.4 BorgBackup

Mecanismo: repositorio chunk-based con deduplicación global (no por
archivo, por bloque de 64 KiB-1 MiB), compresión y cifrado.

Ventajas:

  • Deduplicación independiente del sistema de archivos subyacente. Funciona sobre NTFS, FAT, exFAT, etc. sin depender de hardlinks.
  • Compresión Zstandard configurable (niveles 1-22).
  • Cifrado autenticado AES-256 con HMAC-SHA256.
  • Verificación de integridad mediante checksums SHA-256 en cada chunk.
  • Montaje FUSE nativo.
  • Madurez: 15+ años de desarrollo continuo.

Limitación principal: no está diseñado para backup directo a la nube
(aunque se puede usar rclone como capa de transporte).

Conclusión: BorgBackup es la opción superior para backup a disco
externo local.


4. Arquitectura Propuesta

4.1 Visión general del sistema

┌─────────────────────────────────────────────────────────┐
│                   SISTEMA (/)                           │
│  /home  /etc  /root  /var/www  /opt  /usr/local        │
└──────────────┬──────────────────────────────────────────┘
               │
               │ rsync / borg mount
               ▼
┌─────────────────────────────────────────────────────────┐
│               backup.sh (orquestador)                   │
│                                                         │
│  1. Collect metadata (packages, sources, snaps, ...)    │
│  2. borg create --compression zstd,3                    │
│  3. borg prune (retención automática)                   │
│  4. Logging + notificación                              │
└──────────────┬──────────────────────────────────────────┘
               │
               │ borg create / extract / mount
               ▼
┌─────────────────────────────────────────────────────────┐
│          DISCO EXTERNO (NTFS 1.9 TB)                    │
│                                                         │
│  Backups_linux/                                         │
│  ├── borg/aorsrv/   ← Repositorio Borg (cifrado)        │
│  ├── meta/aorsrv/   ← Metadatos en texto plano          │
│  ├── logs/aorsrv/   ← Historial de ejecución            │
│  └── backup.sh      ← El script mismo                   │
└─────────────────────────────────────────────────────────┘

Enter fullscreen mode Exit fullscreen mode

4.2 Flujo de ejecución de backup.sh now

[Inicio]
  │
  ├─ check: borg instalado?
  ├─ check: disco montado?
  ├─ check: repositorio existe? (init si no)
  ├─ acquire: flock() (evitar concurrencia)
  │
  ├─ collect_metadata():
  │   ├─ dpkg --get-selections > packages.list
  │   ├─ apt-mark showmanual > packages_manual.list
  │   ├─ cp /etc/apt/sources* meta/sources/
  │   ├─ snap list > snaps.list
  │   ├─ flatpak list > flatpak.list
  │   ├─ systemctl list-unit-files > services.list
  │   ├─ getent passwd > users.list
  │   └─ lsblk > disk_layout.txt
  │
  ├─ borg create:
  │   ├─ compression: zstd,3
  │   ├─ one-file-system: sí
  │   ├─ exclude-caches: sí
  │   ├─ includes: /home /etc /root /var/www /opt /usr/local ...
  │   ├─ excludes: /proc /sys /dev /run /tmp /mnt /media *.iso *.vdi ...
  │   └─ output: borg_repo::hostname-YYYYMMDD_HHMMSS
  │
  ├─ if success:
  │   ├─ borg prune (keep-daily=7, keep-weekly=4, keep-monthly=6)
  │   ├─ copy metadata to meta/ dir
  │   └─ log success
  │
  └─ if failure:
      └─ log error + notify if configured

[Fin]

Enter fullscreen mode Exit fullscreen mode

4.3 Estructura de un snapshot Borg

Cada snapshot contiene rutas relativas a / para permitir extracción
directa en el lugar correcto. Los metadatos se almacenan en una ruta
predecible backup-meta-{timestamp}/meta/:

hostname-20260722_142530/
├── home/aor/...
├── etc/ssh/sshd_config
├── etc/hostname
├── root/.bashrc
├── var/www/html/index.html
├── opt/myapp/config.yml
├── usr/local/bin/myscript
├── var/spool/cron/crontabs/aor
└── backup-meta-20260722_142530/
    └── meta/
        ├── system_info.txt
        ├── packages.list
        ├── packages_manual.list
        ├── sources/sources.list
        ├── sources/sources.list.d/
        ├── sources/trusted.gpg
        ├── snaps.list
        ├── flatpak.list
        ├── services_enabled.list
        ├── users.list
        ├── disk_layout.txt
        ├── network.txt
        ├── git_repos.txt
        ├── dev_environments.txt
        ├── excluded_report.txt
        └── vm_images.txt

Enter fullscreen mode Exit fullscreen mode

Nota: La ruta de metadatos es siempre backup-meta-{YYYYMMDD_HHMMSS}/meta/. El
timestamp se extrae del nombre del snapshot (hostname-{timestamp}),
permitiendo a los comandos test-restore, restore-dry-run y restore-full localizar los
metadatos automáticamente sin configuración adicional. vm_images.txt contiene
solo inventario — las imágenes de VM se excluyen del backup por su gran tamaño.

La ruta de metadatos es siempre backup-meta-{YYYYMMDD_HHMMSS}/meta/. El
timestamp se extrae del nombre del snapshot (hostname-{timestamp}),
permitiendo a los comandos test-restore y restore-full localizar los
metadatos automáticamente sin configuración adicional.

4.4 Gestión de metadatos fuera del repositorio

Además de almacenar los metadatos dentro de cada snapshot, el script copia
los metadatos comprimidos a meta/hostname/ en el disco de backup. Esto
permite:

  • Consultar la lista de paquetes sin montar el repositorio Borg.
  • Verificar rápidamente el contenido de un backup sin extraer nada.
  • Acceder a los metadatos incluso si el repositorio Borg se corrompe.

5. Evaluación Comparativa

5.1 Métricas del sistema real

Las métricas que siguen se obtuvieron del primer backup completo del
sistema de referencia (Ubuntu 22.04, ~360 GB en /):

Métrica Valor
Archivos en el sistema ~2.500.000
Tamaño raw de los datos incluidos 145 GB
Tamaño comprimido (zstd,3) 100 GB
Tamaño deduplicado en repositorio 80 GB
Ratio de deduplicación ~1,8x
Duración del backup completo 3h 27m
Conexión del disco externo USB 2.0 (480 Mbps)
Sistema de archivos destino NTFS (ntfs-3g FUSE)

5.2 Proyección de espacio en disco

Con la política de retención actual (7 diarios + 4 semanales + 6
mensuales) y un crecimiento estimado de 2-3 GB/mes en datos nuevos:

Plazo Tamaño estimado Disco libre (418 GB)
Inicial (full) 80 GB 338 GB
+6 meses ~95 GB ~323 GB
+12 meses ~110 GB ~308 GB

El disco de 1,9 TB con 418 GB libres tiene capacidad para más de 3 años
de backups sin necesidad de ampliar.

5.3 Proyección de tiempo de ejecución

El tiempo depende del tipo de backup y del medio de almacenamiento:

Tipo USB 2.0 (actual) USB 3.0 / SATA
Primer backup (full) 3-4 horas 30-60 min
Backup incremental diario 3-8 minutos 1-3 minutos
borg check --verify-data 2-3 horas 20-40 min
borg prune + compact < 1 minuto < 30 seg

Los incrementales son rápidos porque Borg solo procesa los chunks que
cambiaron. En un uso normal de escritorio (documentos, navegación, correo),
el cambio diario es de 100-500 MB. Solo si se instalan paquetes grandes o
se descargan archivos pesados el incremental se alarga.

5.4 Matriz de características

Característica rsync rsnapshot restic BorgBackup
Deduplicación No Hardlinks Sí (bloques) Sí (bloques)
Compresión No No Sí (zstd)
Cifrado No No Sí (AES-256)
Verificación No No SHA-256 SHA-256
Montaje FUSE N/A N/A
Restauración granular Inmediata Inmediata vía mount vía mount
Backup remoto nativo No Sí (multi-cloud) No (con rclone sí)
FS subyacente Cualquiera Hardlinks req. Cualquiera Cualquiera
Dependencias Ninguna rsync Binario único python3
Madurez 25+ años 15+ años 7+ años 15+ años

6. Garantías de Restauración

6.1 Nivel 1: Restauración por archivo

Para recuperar un archivo o directorio concreto sin necesidad de montar
el snapshot completo:

backup.sh restore aorsrv-20260722_142530 etc/hostname ./
backup.sh restore aorsrv-20260722_142530 home/aor/documentos/importante.pdf /tmp/

Enter fullscreen mode Exit fullscreen mode

Borg extrae la ruta exacta del archive y la deposita en el destino
indicado. No requiere montaje FUSE ni permisos de root (a menos que el
destino los requiera). El comando restore también permite restaurar
archivos del snapshot sin tener que navegar manualmente.

6.2 Nivel 2: Restauración por directorio (montaje FUSE)

Para explorar y copiar múltiples archivos sin extraer todo el snapshot:

backup.sh mount aorsrv-20260722_142530
ls /mnt/backup_drive/Backups_linux/mnt/aorsrv-20260722_142530/
cp -r /mnt/backup_drive/Backups_linux/mnt/aorsrv-20260722_142530/home/aor/ ./recuperado/
backup.sh umount

Enter fullscreen mode Exit fullscreen mode

El montaje FUSE es de solo lectura. Se pueden usar herramientas
estándar (cp, rsync, find, grep) sobre los archivos montados.
Ideal para restaurar directorios enteros sin extraer el snapshot completo
al sistema de archivos.

6.3 Nivel 3: Restauración completa del sistema (desastre)

Para recuperar un sistema desde cero tras un fallo catastrófico:

# En una instalación limpia de Ubuntu:
sudo apt install borgbackup
# Montar disco externo con el backup
backup.sh restore-full aorsrv-20260722_142530

Enter fullscreen mode Exit fullscreen mode

restore-full es un asistente interactivo que guía al usuario por:
instalación de Borg, restauración de fuentes APT, reinstalación de
paquetes, extracción de archivos y tareas post-restauración. Está
diseñado para que un usuario con conocimientos básicos de Linux pueda
recuperar el sistema siguiendo las instrucciones en pantalla.

6.4 Verificación de restaurabilidad

backup.sh incluye verificación de integridad a tres niveles:

  1. Por comando: borg check verifica que todos los chunks son legibles y que sus checksums coinciden.
  2. Por snapshot: backup.sh mount <snap> y navegación manual comprueba que los archivos están accesibles.
  3. Por repositorio: borg info muestra el ratio de deduplicación, que sirve como indicador de salud (un ratio anómalo puede indicar corrupción).

7. Decisiones de Diseño

7.1 ¿Por qué un script y no una herramienta con interfaz?

Un script bash no requiere ni interfaz gráfica, ni servidor, ni base de
datos. Funciona en cualquier terminal, incluso sobre SSH, en una sesión
de recovery, o desde un live USB. Es editable con cualquier editor de
texto, se puede auditar línea por línea, y no introduce dependencias
adicionales más allá de las que ya necesita Borg. No hay riesgo de que
una actualización de la GUI rompa el backup: si bash funciona, el script
funciona.

7.2 ¿Por qué la configuración en variables del script?

Un solo archivo autocontenido. No hay archivos de configuración externos
que puedan perderse, olvidarse al copiar el script a otro equipo, o
desincronizarse. Se editan 3 variables (BACKUP_BASE, HOSTNAME,
PASSPHRASE_FILE) y el sistema está operativo. La configuración se
exporta con backup.sh export-config para uso en otros equipos.

7.3 ¿Por qué metadatos fuera del repositorio?

Para poder consultar la lista de paquetes, fuentes APT o servicios del
sistema sin tener que montar el repositorio Borg. Si el disco externo
está conectado pero no se quiere (o no se puede) ejecutar Borg, los
metadatos en texto plano son accesibles con cat, grep o less.
Además, proporciona una capa de redundancia: si el repositorio Borg se
corrompe, los metadatos del sistema sobreviven en texto plano.

7.4 ¿Por qué repokey y no keyfile?

En el modo repokey, la clave de cifrado viaja dentro del propio
repositorio. No se necesita gestionar un archivo de clave aparte. La
clave está protegida por la frase de paso (PBKDF2), por lo que tener el
repo no basta para descifrarlo. En modo keyfile, si se pierde el
archivo de clave, el repositorio es irrecuperable aunque se tenga la
frase de paso. repokey reduce el riesgo de pérdida de clave a cambio
de una protección ligeramente menor (la clave está en el repo, no en un
archivo separado).

7.5 ¿Por qué compresión zstd,3?

Zstandard en nivel 3 ofrece la mejor relación compresión/velocidad en
hardware moderno (CPU de los últimos 10 años). Comprime aproximadamente
igual que gzip -6 pero 2-3 veces más rápido. Niveles superiores (10-19)
apenas mejoran la compresión para datos mixtos (binarios + texto) y
ralentizan significativamente el backup. Nivel 3 es el recomendado por
los propios desarrolladores de Borg para uso general.

7.6 ¿Por qué capturar colas de logs y no los logs completos?

/var/log/ puede ocupar fácilmente 500 MB o más, y la mayoría del
contenido son líneas antiguas sin valor para una restauración. Capturar
las últimas 200 líneas de los logs del sistema proporciona el contexto
necesario para diagnosticar el estado del sistema en el momento del
backup (errores recientes, arranques, apagados, problemas de red) sin
el peso de almacenar cientos de megabytes de registros históricos que
ya están en el sistema original.

7.7 ¿Por qué pre-backup hooks para bases de datos?

Uno de los errores más comunes en backups de Linux es copiar los archivos
raw de bases de datos (/var/lib/mysql/, /var/lib/postgresql/) mientras
el motor está en ejecución. Esto produce copias inconsistentes que pueden
no ser restaurables.

La alternativa correcta —y la implementada en backup.sh— es realizar
volcados lógicos (dumps) antes de cada backup:

Motor Comando de volcado Portable entre versiones
MySQL/MariaDB mysqldump --all-databases --single-transaction
PostgreSQL pg_dumpall
MongoDB mongodump
Redis SAVE + copia de dump.rdb Parcial (misma versión major)
SQLite .backup vía sqlite3

Ventajas de los dumps frente a copia raw:

  1. Portabilidad: un dump de MySQL 5.7 se restaura en MySQL 8.0, MariaDB 10.x, Percona Server, etc. La copia raw solo funciona con la versión exacta.
  2. Consistencia transaccional: mysqldump --single-transaction garantiza una instantánea consistente del momento en que comenzó el dump.
  3. Espacio: los dumps omiten índices, logs binarios, tablas temporales y páginas no utilizadas. Un dump es típicamente un 30-50% más pequeño que los datos raw.
  4. Restauración selectiva: un dump SQL se puede editar con un editor de texto para restaurar solo una tabla o una fila.
  5. Integridad referencial: los dumps preservan claves foráneas, disparadores, procedimientos almacenados, funciones y vistas en el orden correcto de creación.

Detección automática: el script no asume nada. Detecta qué motores
están en ejecución (pgrep) y si las herramientas de dump están
instaladas (command -v). Solo entonces ejecuta el volcado, sin
intervención del usuario.

Almacenamiento: los dumps se escriben en
/var/backups/pre-backup-hooks/, directorio que está incluido en el
backup (/var/backups está en INCLUDE). Borg los deduplica
automáticamente entre snapshots: solo las páginas de datos que cambian de
un día para otro ocupan espacio nuevo.


8. Casos de Uso y Escenarios

8.1 Uso diario (cron)

El caso más común: el script se ejecuta automáticamente cada día a las 3 AM
via crontab. Como los backups son incrementales, la ventana de ejecución es
corta (10-20 minutos para ~2.5M archivos), y Borg solo almacena los bloques
nuevos desde el último snapshot.

0 3 * * * /home/aor/bin/backup.sh cron

Enter fullscreen mode Exit fullscreen mode

El modo cron desactiva colores, barras de progreso y prompts. Escribe al
log y devuelve código de retorno para que cron envíe alertas por correo si
algo falla:

./backup.sh doctor         # Verificar que el sistema está sano
tail -f "$BACKUP_BASE/logs/$(hostname -s)/backup.log"  # Monitorizar resultado

Enter fullscreen mode Exit fullscreen mode

8.2 Backup antes de una actualización del sistema

Antes de una operación de riesgo (apt upgrade, do-release-upgrade,
cambio de kernel, etc.):

./backup.sh now            # Backup completo justo antes del cambio
sudo apt upgrade           # Aplicar la actualización

Enter fullscreen mode Exit fullscreen mode

Si la actualización introduce regresiones:

./backup.sh diff <snap-pre> <snap-post>   # Ver qué archivos cambiaron
./backup.sh restore <snap-pre> etc/hostname /tmp/  # Recuperar config anterior
./backup.sh mount <snap-pre>              # Inspeccionar el sistema antes del cambio

Enter fullscreen mode Exit fullscreen mode

El snapshot pre-actualización es un punto de restauración completo. No es
necesario hacer backup del sistema completo antes de cada apt install,
pero para operaciones que modifican /etc, kernels o servicios críticos,
el coste de un snapshot incremental extra (~10 minutos, ~270 MB) es mínimo
comparado con el tiempo de depuración si algo sale mal.

8.3 Cambio de disco duro

Escenario: el disco principal falla o se sustituye por uno de mayor
capacidad. El proceso completo con BorgShield:

  1. Conectar disco externo con el backup al nuevo equipo.
  2. Instalar Ubuntu (o Debian) desde USB. No configurar nada aún.
  3. Montar disco externo y verificar accesibilidad:
sudo mount /dev/sdb1 /mnt/backup_drive
mount | grep backup_drive

Enter fullscreen mode Exit fullscreen mode

  1. Copiar backup.sh y ejecutar restore-full:
cp /mnt/backup_drive/Backups_linux/backup.sh ~/
./backup.sh restore-full <ultimo-snapshot>

Enter fullscreen mode Exit fullscreen mode

  1. El asistente guía paso a paso:
    • Instala Borg si no está presente.
    • Pregunta si restaurar fuentes APT (sources.list, GPG keys).
    • Ofrece 3 métodos de restauración de paquetes: manual, dpkg-set-selections, apt-clone.
    • Pide doble confirmación antes de extraer archivos.
    • Muestra tareas post-restauración: hostname, fstab, SSH keys, GRUB.

No es necesario reinstalar el SO desde cero configurándolo primero: los
archivos de configuración del sistema original (resolv.conf, interfaces de
red, fstab, fuentes APT, crontabs, claves SSH) se restauran desde el
backup. Solo el kernel y el cargador de arranque requieren configuración
manual post-restauración (detallada en las tareas post-restauración).

8.4 Múltiples equipos en el mismo disco

Cada equipo se identifica por su $(hostname -s). Con solo copiar backup.sh
y ajustar BACKUP_BASE al mismo disco externo, cada equipo gestiona sus
propios snapshots, metadatos y logs de forma aislada:

/mnt/backup_drive/Backups_linux/
├── borg/portatil/
├── borg/servidor/
├── meta/portatil/
├── meta/servidor/
├── logs/portatil/
└── logs/servidor/

Enter fullscreen mode Exit fullscreen mode

Solo es necesario copiar backup.sh a cada equipo y ajustar
BACKUP_BASE si es necesario.


9. Limitaciones y Trabajo Futuro

9.1 Limitaciones conocidas

  1. Dependencia de BorgBackup: el sistema requiere instalar borgbackup. En sistemas sin acceso a internet, esto puede ser un obstáculo.
  2. Backup remoto no nativo: a diferencia de Restic, Borg no tiene soporte nativo para S3 o Backblaze. Se requiere rclone como capa adicional.
  3. Rendimiento en NTFS: aunque Borg funciona sobre NTFS, el rendimiento puede ser inferior al de ext4 debido a la capa FUSE (ntfs-3g).
  4. Consumo de RAM: Borg utiliza algo de RAM para los índices de chunks (~1 GB por cada TB de datos únicos). En sistemas con poca RAM, puede ser un factor.
  5. Docker experimental: la detección de BBDD dentro de contenedores Docker está desactivada por defecto (DOCKER_BACKUP=false) y requiere que el contenedor tenga las herramientas de dump instaladas.

9.2 Posibles mejoras

  1. Soporte para backup remoto: añadir modo rclone que sincronice el repositorio Borg a la nube.
  2. Notificaciones push: integración con Telegram, Pushover o Gotify.
  3. Interfaz TUI: menú interactivo para usuarios menos técnicos.
  4. Pre/Post hooks: scripts personalizados que se ejecuten antes y después del backup (ej. dump de base de datos).
  5. Reporte HTML: generar un reporte visual del estado del backup.
  6. Soporte LXD/LXC/KVM: detección y backup de contenedores y máquinas virtuales.
  7. borg export-tar: comando para exportar un snapshot como tar (para enviar a otro sistema sin Borg).

10. Conclusiones

backup.sh resuelve los cuatro problemas fundamentales del backup en
Linux para el escenario de disco externo local:

  1. Eficiencia: la deduplicación y compresión de BorgBackup reducen el espacio necesario a aproximadamente la mitad del tamaño original, y el crecimiento con el tiempo es mínimo (~2-3 GB/mes).
  2. Fiabilidad: los checksums SHA-256 verifican cada byte almacenado. El comando check --full garantiza que todos los datos son recuperables.
  3. Restaurabilidad: tres niveles de restauración (archivo, directorio, sistema completo) cubren desde la pérdida accidental de un documento hasta un desastre total. El modo restore-full guía al usuario paso a paso.
  4. Seguridad: cifrado AES-256 con frase de paso, archivo de clave con permisos 600, y disco externo desconectable (protección contra ransomware).

Frente a las alternativas (rsync, rsnapshot, restic), BorgBackup ofrece la
mejor combinación de características para backup local: madurez,
deduplicación real, compresión eficiente, cifrado sólido y verificación
criptográfica.


11. Diferenciadores Clave Respecto a Otras Soluciones

Más allá de las comparativas cuantitativas (espacio, tiempo, compresión),
backup.sh introduce cinco capacidades que no existen juntas en ninguna
otra solución
del ecosistema Linux:

11.1 Restauración virtual (test-restore)

Ninguna herramienta de backup ofrece un comando que verifique la
restaurabilidad semántica de un snapshot sin extraer datos al sistema
de archivos real:

  • borg check verifica integridad técnica (checksums, índices).
  • backup.sh test-restore verifica restaurabilidad semántica: formato de paquetes dpkg, integridad de dumps de BBDD (gunzip -t, tar -tzf, cabeceras mágicas), presencia de rutas esenciales, legibilidad de metadatos del sistema.

Es el equivalente funcional de tar -tvf aplicado a todo el ecosistema
de backup: bases de datos, configuración del sistema, logs, paquetes y
archivos.

11.2 Dumping automático de BBDD sin configuración

Mientras que rsync, rsnapshot, timeshift y Borg puro copian archivos raw
de bases de datos (inconsistentes si el motor está en ejecución),
backup.sh detecta y ejecuta el volcado correcto para cada motor:

Motor backup.sh rsync/rsnapshot/timeshift Borg puro
MySQL mysqldump automático Copia raw (dañada si mysqld activo) Copia raw (dañada)
PostgreSQL pg_dumpall automático Copia raw (dañada) Copia raw (dañada)
MongoDB mongodump automático Copia raw (dañada) Copia raw (dañada)
Redis SAVE + RDB Copia raw Copia raw

No requiere configurar credenciales, hooks ni scripts externos. Detecta
el motor por pgrep + command -v.

11.3 Metadatos completos del sistema en cada snapshot

Cada snapshot contiene 14 categorías de metadatos que van mucho más allá
de lo que cualquier herramienta de backup captura:

  • Lista de paquetes (completa + manuales).
  • Repositorios APT con GPG keys (restaurables).
  • Snaps, flatpaks, servicios systemd, usuarios, discos, red.
  • Colas de logs (200 últimas líneas: contexto sin peso).

Esto significa que, con un solo snapshot, se puede reconstruir el perfil
completo de software del sistema original sin necesidad de tener el
sistema funcionando.

11.4 Restauración guiada interactiva

Mientras que Borg, restic y rsync ofrecen extract/restore como
comandos planos, restore-full implementa un asistente paso a paso
que:

  1. Verifica que el snapshot existe y es legible.
  2. Detecta si Borg está instalado en el sistema destino.
  3. Pregunta si restaurar fuentes APT (con copia real).
  4. Ofrece 3 métodos distintos de restauración de paquetes.
  5. Pide doble confirmación antes de extraer archivos.
  6. Muestra tareas post-restauración.

Además, restore-dry-run permite ejecutar el mismo flujo en modo
simulación: muestra todos los pasos, comandos, paquetes y archivos
que se restaurarían sin modificar absolutamente nada del sistema. Incluye:

  • Entornos de desarrollo: resumen por tecnología con comandos de regeneración
  • Repositorios git: filtrados por /home/ y /opt/, con branch, commit y remote
  • Máquinas virtuales: inventario de imágenes encontradas con nota "NO respaldada"
  • Snaps y flatpaks: nombres reales con comandos de instalación (snap install, flatpak install flathub)
  • Selección de snapshot: el comando lista snapshots numerados vía list_snapshots()

Es la herramienta ideal para verificar el contenido de un snapshot antes de
comprometerse con una restauración real.

11.5 Arquitectura autocontenida

A diferencia de las soluciones que requieren:

  • Múltiples archivos de configuración (rsnapshot: rsnapshot.conf, scripts de pre/post-backup, etc.).
  • Bases de datos de estado (Duplicity: archivos de firmas).
  • Agentes en segundo plano (timeshift: daemon).

backup.sh es un único archivo bash. Se copia al equipo, se editan 3
variables, se ejecuta init, y el sistema de backup está operativo.
La configuración, los logs, los metadatos y el repositorio están en el
disco externo, no en el sistema.

11.6 Reporte de archivos excluidos

Todas las herramientas de backup tienen exclusiones, pero ninguna informa
al usuario de qué archivos ha excluido. backup.sh ejecuta, tras cada
backup exitoso, un escáner sobre los directorios incluidos que cuenta
archivos y directorios coincidentes con cada patrón de exclusión.

El resultado se muestra en pantalla y se guarda dentro del snapshot como
meta/excluded_report.txt. En restauración, el usuario puede consultar
este reporte para saber qué archivos no están en el backup y cómo
reconstruirlos.

11.7 Captura de repositorios git, entornos de desarrollo y configuración de usuario

Cada snapshot incluye, además de los archivos del sistema, metadatos
estructurados sobre el perfil de usuario:

Repositorios git (meta/git_repos.txt):
ruta, remote origin, rama activa, último commit y número de cambios sin
publicar de cada repositorio .git. Permite saber exactamente qué clonar
(o qué commit revisar) en una restauración.

Entornos de desarrollo (meta/dev_environments.txt):
manifiestos de proyectos (package.json, Cargo.toml, requirements.txt,
pyproject.toml, Gemfile, go.mod, composer.json, Mix.lock, rebar.config).
Cada entrada incluye ruta, tecnología, gestor y comando de regeneración.

Configuración de snaps (meta/snap_config.txt):
snap get ejecutado sobre cada snap instalado. La configuración de las
aplicaciones snap no reside en archivos planos del sistema de archivos,
sino en el almacenamiento interno de snapd. Sin esta captura, las
configuraciones se pierden aunque el snap se reinstale.

Flatpaks completo (meta/flatpak_full.txt):
aplicaciones, runtimes, remotes y overrides de permisos. Los overrides
(permisos por aplicación) no se almacenan en archivos del sistema de
archivos, sino en el almacén de datos de flatpak.

Configuración del escritorio (meta/dconf_dump.txt):
dconf dump / produce texto plano con toda la configuración del
entorno de escritorio (GNOME, Unity, etc.). Restaurable con
dconf load / < meta/dconf_dump.txt.

Claves GPG (meta/gpg_public_keys.asc + meta/gpg_ownertrust.txt):
exportación armored de claves públicas y marcas de confianza. Las claves
privadas ya están en ~/.gnupg/ (respaldadas dentro de /home).

Claves SSH autorizadas (meta/ssh_authorized_keys.txt):
inventario de claves públicas autorizadas por usuario. Las claves
privadas y configuraciones SSH ya están en ~/.ssh/ (respaldadas).

Conexiones NetworkManager (meta/nm_connections.txt):
resumen legible de conexiones de red configuradas. Los archivos reales
están en /etc/NetworkManager/system-connections/ (respaldados).

Imágenes de máquinas virtuales (meta/vm_images.txt):
inventario de imágenes VM encontradas en /home/, /opt/, etc. (formatos:
vdi, vmdk, qcow2, vhd, vhdx, ova, ovf). Solo inventario — no se respaldan
por su gran tamaño. En restauración se muestran con la advertencia de que
requieren un backup específico.

Esto resuelve los problemas clásicos en restauraciones:

  1. "Tenía varios repositorios git ¿cuáles eran y dónde estaban?"
  2. "Tengo el código, pero las dependencias se excluyeron y no recuerdo cómo reinstalarlas."
  3. "Perdí la configuración de los snaps y flatpaks (no está en archivos)."
  4. "No recuerdo qué claves GPG/SSH había configuradas."
  5. "¿Qué conexiones de red tenía y cómo se llamaban?"
  6. "¿Tenía máquinas virtuales en este equipo? ¿Qué imágenes y dónde estaban?"

Los manifiestos y configuraciones se respaldan (están dentro de rutas
incluidas), y el script registra metadatos sobre ellos para que la
restauración sea guiada.


12. Gestión de Dependencia: BorgBackup

backup.sh depende de BorgBackup. Si Borg cambia su CLI, formato de
salida o flags, el script puede fallar.

12.1 Verificación post-actualización

El script incluye check_borg_compat() que verifica automáticamente que
la versión instalada de Borg soporte todas las opciones utilizadas.
Esta función se ejecuta:

  • En cmd_now() antes de cada backup (bloqueante: si falta algo, aborta).
  • En cmd_doctor() como diagnóstico (informativo: muestra advertencias).
backup.sh doctor          # Diagnóstico completo (incluye compatibilidad)
backup.sh verify          # Verificar passphrase
backup.sh test-restore "$(backup.sh list | head -2 | tail -1 | awk '{print $1}')"

Enter fullscreen mode Exit fullscreen mode

12.2 Puntos de fallo conocidos

Componente Dependencia Borg Verificado por Riesgo
borg create --one-file-system, --numeric-ids, --exclude-nobackups, --exclude-caches, --compression, --stats, --progress check_borg_compat Bajo
borg info --json Estructura JSON de salida check_borg_compat Medio
borg list --format="..." Placeholders de formato ({archive}, {time}, {size}) check_borg_compat Medio
borg check --verify-data Flag disponible desde Borg 1.2 check_borg_compat Medio
borg compact Comando disponible desde Borg 1.2 check_borg_compat Bajo
borg prune --keep-daily, --keep-weekly, --keep-monthly, --keep-yearly check_borg_compat Bajo
borg init --encryption Flag --encryption check_borg_compat Bajo
borg extract Comportamiento de rutas Verificación manual Bajo

12.4 Lecciones aprendidas: bugs cazados durante el desarrollo

Durante las sesiones de desarrollo y shellcheck del script, se
identificaron y corrigieron varios bugs sutiles relacionados con el uso
de set -e y operadores bash:

Bug Síntoma Causa Fix
load_passphrase mata el script El script termina silenciosamente sin error aparente [ -z "$var" ] && error retorna 1 cuando $var no está vacía (cortocircuito &&), y set -e propaga el exit code no-zero if [ -z "$var" ]; then error; fiif no propaga exit code
rotate_log mata el script en 1ª ejecución El script muere al hacer el primer backup (log no existe) `[ -f "$log" ] \ \
{% raw %}DRY_RUN=true por env no funciona Dry-run se ignora aunque se pase como variable de entorno DRY_RUN=false en el script es asignación directa, no condicional, y sobrescribe el env DRY_RUN="${DRY_RUN:-false}" — solo usa el default si env no está definido
DRY_RUN imprime pero ejecuta igual El mensaje "MODO SIMULACIÓN" se muestra, pero el backup real se ejecuta El bloque dry-run no tenía return 0, por lo que el flujo caía en borg create Añadir return 0
tr -d ' ' no elimina newlines [: entero esperado] en conteos de líneas de git, flatpak, etc. tr -d ' ' solo elimina espacios, no newlines, carriage returns, etc. tr -d '[:space:]'
PASSPHRASE_FILE ignorado con sudo sudo ./backup.sh now busca passphrase en /root/ en vez de /home/user/ $HOME cambia a /root con sudo, pero la passphrase está en el home del usuario real Detectar SUDO_USER y usar su home; mkdir con fallback a sudo mkdir
borg extract -C no existe en Borg 1.2.0 backup.sh restore falla: flag --destination/-C no soportado Borg 1.2.0 no implementa -C; apareció en Borg 1.4 Reemplazar por pushd "$dir" && borg extract && popd
borg list REPO::ARCHIVE extremadamente lento El script tardaba minutos en verificar si un snapshot existe borg list recorre los 2.5M de archivos; borg info es O(1) Reemplazar borg list REPO::ARCHIVE por borg info REPO::ARCHIVE
{NL} vs \n en format string de Borg borg list --format no interpretaba \n Borg 1.2.0 usa {NL} como placeholder de nueva línea, no \n Usar {NL} en lugar de \n en format strings
\033 entre comillas simples no es escape Los colores ANSI no se mostraban '\033' en bash es literal \033 (tres caracteres), no el byte escape Usar $'\033' (ANSI-C quoting) para que bash interprete el escape
`grep -c echo "0"` produce doble salida Cuando grep encuentra 0 coincidencias, imprime "0" en stdout pero retorna 1. `\
{% raw %}${manual_pkgs - 10} no es aritmética bash Error de sintaxis: "entero esperado" En bash la resta aritmética requiere $(( ... )), los espacios alrededor del operador no bastan Usar $(( manual_pkgs - 10 ))

Lección general: set -e no es una red de seguridad fiable. Cualquier
expresión que pueda retornar no-zero —incluso como parte de un && o ||
que parece inocuo— mata el script sin mensaje de error. Siempre que sea
posible, usar if en lugar de &&/|| para dependencias críticas.

12.5 Prácticas recomendadas

  1. Ejecutar backup.sh doctor tras cada apt upgrade borgbackup para verificar que check_borg_compat() no detecta incompatibilidades.
  2. Mantener copia del script en el disco de backup (no solo en el sistema).
  3. Si Borg cambia su formato de repo, el repo existente sigue siendo legible por versiones anteriores — no actualizar Borg sin verificar.
  4. Usar backup.sh test-restore <ultimo-snapshot> tras cada actualización para verificar que la restauración sigue funcionando.

13. Borg es el Taladro, backup.sh es el Robot — El Valor del Sistema Completo

BorgBackup es el motor, pero nosotros construimos un sistema completo
orquestado alrededor. Esto es lo que aportamos:

13.1 Automatización de backup completo

  • backup.sh now — un solo comando que hace backup del sistema completo, no solo archivos. Borg por sí solo no sabe qué incluir, ni organiza todo esto.
  • Detección automática de qué servicios/BDD están corriendo (MySQL, PostgreSQL, MongoDB, Redis, SQLite, Docker) y volcado consistente de cada uno.

13.2 Metadatos del sistema (lo que hace restaurable el backup)

Borg solo guarda archivos. Nosotros capturamos el estado del sistema
completo en cada snapshot:

  • Paquetes instalados (apt, snaps, flatpaks)
  • Repositorios apt, PPAs, claves GPG
  • Crontabs de todos los usuarios
  • Configuración de red (NetworkManager, iptables, nftables)
  • Claves SSH autorizadas, GPG, dconf
  • Repositorios git y entornos de desarrollo
  • Inventario de máquinas virtuales (vm_images.txt — referencia, no respaldadas)
  • Servicios systemd, discos, usuarios

Sin esto, restaurar un sistema desde un backup de Borg te deja con
archivos, pero no sabes QUÉ instalar, QUÉ configurar, CÓMO reconstruir.

Read the original source
Dev.to

Publisher

Originally by Arcadio Ortega Reinoso


0 Comments

Log in to join the conversation.

No comments yet. Be the first to share your thoughts.