<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Arcadio Ortega Reinoso</title>
    <description>The latest articles on DEV Community by Arcadio Ortega Reinoso (@arcadio_ortega).</description>
    <link>https://dev.to/arcadio_ortega</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3369521%2F04dda67a-9b7b-4f75-a46c-1a4b81a12545.png</url>
      <title>DEV Community: Arcadio Ortega Reinoso</title>
      <link>https://dev.to/arcadio_ortega</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arcadio_ortega"/>
    <language>en</language>
    <item>
      <title>BorgShield: Sistema de Backup Linux Eficiente, Fiable y Verificable</title>
      <dc:creator>Arcadio Ortega Reinoso</dc:creator>
      <pubDate>Thu, 23 Jul 2026 17:51:24 +0000</pubDate>
      <link>https://dev.to/arcadio_ortega/borgshield-sistema-de-backup-linux-eficiente-fiable-y-verificable-4iad</link>
      <guid>https://dev.to/arcadio_ortega/borgshield-sistema-de-backup-linux-eficiente-fiable-y-verificable-4iad</guid>
      <description>&lt;h2&gt;
  
  
  Un análisis técnico basado en BorgBackup para entornos Debian/Ubuntu
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Autor:&lt;/strong&gt; Arcadio Ortega Reinoso&lt;br&gt;
&lt;strong&gt;Versión del sistema:&lt;/strong&gt; 2.1.0&lt;br&gt;
&lt;strong&gt;Fecha:&lt;/strong&gt; Julio 2026&lt;br&gt;
&lt;strong&gt;Plataforma objetivo:&lt;/strong&gt; Debian 11+ / Ubuntu 22.04+ (x86_64)&lt;/p&gt;



&lt;p&gt;Puedes encontrarlo en: &lt;a href="https://github.com/aortrei469/BorgShield" rel="noopener noreferrer"&gt;BorgShield&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Fortalezas Diferenciales
&lt;/h2&gt;

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

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

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


&lt;h2&gt;
  
  
  Resumen
&lt;/h2&gt;

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

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


&lt;h2&gt;
  
  
  1. Ventaja Diferencial
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1.1 Matriz de diferenciación
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capacidad&lt;/th&gt;
&lt;th&gt;rsync&lt;/th&gt;
&lt;th&gt;rsnapshot&lt;/th&gt;
&lt;th&gt;restic&lt;/th&gt;
&lt;th&gt;duplicity&lt;/th&gt;
&lt;th&gt;timeshift&lt;/th&gt;
&lt;th&gt;Borg CLI&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;backup.sh&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Un solo archivo&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sin archivos de configuración externos&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dumps BBDD automáticos&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test-restore virtual&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simulación restauración&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metadatos de paquetes&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restauración guiada&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reporte de exclusiones&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mapa de repos git&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entornos de desarrollo&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inventario de VMs&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crontab-ready&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modo silencioso/sin prompts&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ninguna herramienta existente cubre más de 2 de estas 13 capacidades.&lt;/p&gt;
&lt;h3&gt;
  
  
  1.2 Lo que otros tienen y backup.sh no
&lt;/h3&gt;

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

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


&lt;h2&gt;
  
  
  2. Introducción y Planteamiento del Problema
&lt;/h2&gt;
&lt;h3&gt;
  
  
  2.1 El problema del backup en Linux
&lt;/h3&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ausencia de deduplicación&lt;/strong&gt;: los backups completos duplican datos que
no han cambiado, consumiendo espacio innecesario.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falta de verificación&lt;/strong&gt;: sin checksums, no hay garantía de que los
datos almacenados sean recuperables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencia del sistema de archivos&lt;/strong&gt;: 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restauración compleja&lt;/strong&gt;: recuperar un sistema completo desde cero
requiere múltiples herramientas y conocimientos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Carencia de cifrado&lt;/strong&gt;: los datos en disco externo viajan sin protección.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  2.2 Requisitos del sistema
&lt;/h3&gt;

&lt;p&gt;El sistema que nos ocupa presenta las siguientes características:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Métrica&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Distribución&lt;/td&gt;
&lt;td&gt;Ubuntu 22.04.5 LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kernel&lt;/td&gt;
&lt;td&gt;5.15.x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paquetes totales&lt;/td&gt;
&lt;td&gt;~3200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paquetes manuales&lt;/td&gt;
&lt;td&gt;~460&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Datos en /&lt;/td&gt;
&lt;td&gt;~360 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disco de backup&lt;/td&gt;
&lt;td&gt;NTFS 1.9T (418 GB libres)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;El objetivo es diseñar un sistema de backup que cumpla:&lt;/p&gt;

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


&lt;h2&gt;
  
  
  3. Soluciones Existentes y sus Limitaciones
&lt;/h2&gt;
&lt;h3&gt;
  
  
  3.1 rsync con hardlinks (rsnapshot)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mecanismo:&lt;/strong&gt; &lt;code&gt;rsync -aAX --link-dest=&amp;lt;anterior&amp;gt;&lt;/code&gt; + &lt;code&gt;cp -al&lt;/code&gt; para crear&lt;br&gt;
snapshots con hardlinks a archivos sin cambios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ventajas:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Los archivos son directamente accesibles (cada snapshot es un directorio).&lt;/li&gt;
&lt;li&gt;Sin dependencias adicionales más allá de rsync.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitaciones:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Proyección para nuestro sistema:&lt;/strong&gt; Con ~360 GB de origen y rotación de 3&lt;br&gt;
fulls, ocuparíamos ~1.1 TB en 12 meses. En un disco de 1.9 TB con 418 GB&lt;br&gt;
libres, esto es inviable a largo plazo.&lt;/p&gt;
&lt;h3&gt;
  
  
  3.2 Restic
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mecanismo:&lt;/strong&gt; repositorio chunk-based con deduplicación y cifrado,&lt;br&gt;
similar a Borg pero con énfasis en almacenamiento en la nube.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ventajas:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excelente para backups remotos (S3, Backblaze, Azure).&lt;/li&gt;
&lt;li&gt;Deduplicación y cifrado.&lt;/li&gt;
&lt;li&gt;FUSE mount.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitaciones:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compresión menos eficiente que Borg en escenarios locales (no usa zstd).&lt;/li&gt;
&lt;li&gt;Menor madurez en el ecosistema (Borg tiene 15+ años).&lt;/li&gt;
&lt;li&gt;Montaje FUSE menos estable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3.3 Timeshift (modo rsync)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mecanismo:&lt;/strong&gt; rsync con hardlinks + interfaz gráfica.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ventajas:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interfaz amigable.&lt;/li&gt;
&lt;li&gt;Bueno para snapshots del sistema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitaciones:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No cifra.&lt;/li&gt;
&lt;li&gt;No comprime.&lt;/li&gt;
&lt;li&gt;No tiene verificación.&lt;/li&gt;
&lt;li&gt;Depende de hardlinks.&lt;/li&gt;
&lt;li&gt;Orientado a restauración del sistema, no de archivos de usuario.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3.4 BorgBackup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mecanismo:&lt;/strong&gt; repositorio chunk-based con deduplicación global (no por&lt;br&gt;
archivo, por bloque de 64 KiB-1 MiB), compresión y cifrado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ventajas:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Limitación principal:&lt;/strong&gt; no está diseñado para backup directo a la nube&lt;br&gt;
(aunque se puede usar rclone como capa de transporte).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusión:&lt;/strong&gt; BorgBackup es la opción superior para backup a disco&lt;br&gt;
externo local.&lt;/p&gt;


&lt;h2&gt;
  
  
  4. Arquitectura Propuesta
&lt;/h2&gt;
&lt;h3&gt;
  
  
  4.1 Visión general del sistema
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│                   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                   │
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  4.2 Flujo de ejecución de &lt;code&gt;backup.sh now&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Inicio]
  │
  ├─ check: borg instalado?
  ├─ check: disco montado?
  ├─ check: repositorio existe? (init si no)
  ├─ acquire: flock() (evitar concurrencia)
  │
  ├─ collect_metadata():
  │   ├─ dpkg --get-selections &amp;gt; packages.list
  │   ├─ apt-mark showmanual &amp;gt; packages_manual.list
  │   ├─ cp /etc/apt/sources* meta/sources/
  │   ├─ snap list &amp;gt; snaps.list
  │   ├─ flatpak list &amp;gt; flatpak.list
  │   ├─ systemctl list-unit-files &amp;gt; services.list
  │   ├─ getent passwd &amp;gt; users.list
  │   └─ lsblk &amp;gt; 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]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  4.3 Estructura de un snapshot Borg
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;La ruta de metadatos es siempre &lt;code&gt;backup-meta-{YYYYMMDD_HHMMSS}/meta/&lt;/code&gt;. El&lt;br&gt;
timestamp se extrae del nombre del snapshot (&lt;code&gt;hostname-{timestamp}&lt;/code&gt;),&lt;br&gt;
permitiendo a los comandos &lt;code&gt;test-restore&lt;/code&gt; y &lt;code&gt;restore-full&lt;/code&gt; localizar los&lt;br&gt;
metadatos automáticamente sin configuración adicional.&lt;/p&gt;
&lt;h3&gt;
  
  
  4.4 Gestión de metadatos fuera del repositorio
&lt;/h3&gt;

&lt;p&gt;Además de almacenar los metadatos dentro de cada snapshot, el script copia&lt;br&gt;
los metadatos comprimidos a &lt;code&gt;meta/hostname/&lt;/code&gt; en el disco de backup. Esto&lt;br&gt;
permite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consultar la lista de paquetes sin montar el repositorio Borg.&lt;/li&gt;
&lt;li&gt;Verificar rápidamente el contenido de un backup sin extraer nada.&lt;/li&gt;
&lt;li&gt;Acceder a los metadatos incluso si el repositorio Borg se corrompe.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  5. Evaluación Comparativa
&lt;/h2&gt;
&lt;h3&gt;
  
  
  5.1 Métricas del sistema real
&lt;/h3&gt;

&lt;p&gt;Las métricas que siguen se obtuvieron del primer backup completo del&lt;br&gt;
sistema de referencia (Ubuntu 22.04, ~360 GB en &lt;code&gt;/&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Métrica&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Archivos en el sistema&lt;/td&gt;
&lt;td&gt;~2.500.000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tamaño raw de los datos incluidos&lt;/td&gt;
&lt;td&gt;145 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tamaño comprimido (zstd,3)&lt;/td&gt;
&lt;td&gt;100 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tamaño deduplicado en repositorio&lt;/td&gt;
&lt;td&gt;80 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ratio de deduplicación&lt;/td&gt;
&lt;td&gt;~1,8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duración del backup completo&lt;/td&gt;
&lt;td&gt;3h 27m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conexión del disco externo&lt;/td&gt;
&lt;td&gt;USB 2.0 (480 Mbps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sistema de archivos destino&lt;/td&gt;
&lt;td&gt;NTFS (ntfs-3g FUSE)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  5.2 Proyección de espacio en disco
&lt;/h3&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plazo&lt;/th&gt;
&lt;th&gt;Tamaño estimado&lt;/th&gt;
&lt;th&gt;Disco libre (418 GB)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inicial (full)&lt;/td&gt;
&lt;td&gt;80 GB&lt;/td&gt;
&lt;td&gt;338 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+6 meses&lt;/td&gt;
&lt;td&gt;~95 GB&lt;/td&gt;
&lt;td&gt;~323 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+12 meses&lt;/td&gt;
&lt;td&gt;~110 GB&lt;/td&gt;
&lt;td&gt;~308 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;El disco de 1,9 TB con 418 GB libres tiene capacidad para más de 3 años&lt;br&gt;
de backups sin necesidad de ampliar.&lt;/p&gt;
&lt;h3&gt;
  
  
  5.3 Proyección de tiempo de ejecución
&lt;/h3&gt;

&lt;p&gt;El tiempo depende del tipo de backup y del medio de almacenamiento:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipo&lt;/th&gt;
&lt;th&gt;USB 2.0 (actual)&lt;/th&gt;
&lt;th&gt;USB 3.0 / SATA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primer backup (full)&lt;/td&gt;
&lt;td&gt;3-4 horas&lt;/td&gt;
&lt;td&gt;30-60 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backup incremental diario&lt;/td&gt;
&lt;td&gt;3-8 minutos&lt;/td&gt;
&lt;td&gt;1-3 minutos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;borg check --verify-data&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2-3 horas&lt;/td&gt;
&lt;td&gt;20-40 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;borg prune&lt;/code&gt; + &lt;code&gt;compact&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&amp;lt; 1 minuto&lt;/td&gt;
&lt;td&gt;&amp;lt; 30 seg&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Los incrementales son rápidos porque Borg solo procesa los chunks que&lt;br&gt;
cambiaron. En un uso normal de escritorio (documentos, navegación, correo),&lt;br&gt;
el cambio diario es de 100-500 MB. Solo si se instalan paquetes grandes o&lt;br&gt;
se descargan archivos pesados el incremental se alarga.&lt;/p&gt;
&lt;h3&gt;
  
  
  5.4 Matriz de características
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;rsync&lt;/th&gt;
&lt;th&gt;rsnapshot&lt;/th&gt;
&lt;th&gt;restic&lt;/th&gt;
&lt;th&gt;BorgBackup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Deduplicación&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Hardlinks&lt;/td&gt;
&lt;td&gt;Sí (bloques)&lt;/td&gt;
&lt;td&gt;Sí (bloques)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compresión&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Sí (zstd)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cifrado&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Sí (AES-256)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verificación&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Montaje FUSE&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restauración granular&lt;/td&gt;
&lt;td&gt;Inmediata&lt;/td&gt;
&lt;td&gt;Inmediata&lt;/td&gt;
&lt;td&gt;vía mount&lt;/td&gt;
&lt;td&gt;vía mount&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backup remoto nativo&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Sí (multi-cloud)&lt;/td&gt;
&lt;td&gt;No (con rclone sí)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FS subyacente&lt;/td&gt;
&lt;td&gt;Cualquiera&lt;/td&gt;
&lt;td&gt;Hardlinks req.&lt;/td&gt;
&lt;td&gt;Cualquiera&lt;/td&gt;
&lt;td&gt;Cualquiera&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependencias&lt;/td&gt;
&lt;td&gt;Ninguna&lt;/td&gt;
&lt;td&gt;rsync&lt;/td&gt;
&lt;td&gt;Binario único&lt;/td&gt;
&lt;td&gt;python3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Madurez&lt;/td&gt;
&lt;td&gt;25+ años&lt;/td&gt;
&lt;td&gt;15+ años&lt;/td&gt;
&lt;td&gt;7+ años&lt;/td&gt;
&lt;td&gt;15+ años&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  6. Garantías de Restauración
&lt;/h2&gt;
&lt;h3&gt;
  
  
  6.1 Nivel 1: Restauración por archivo
&lt;/h3&gt;

&lt;p&gt;Para recuperar un archivo o directorio concreto sin necesidad de montar&lt;br&gt;
el snapshot completo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;backup.sh restore aorsrv-20260722_142530 etc/hostname ./
backup.sh restore aorsrv-20260722_142530 home/aor/documentos/importante.pdf /tmp/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Borg extrae la ruta exacta del archive y la deposita en el destino&lt;br&gt;
indicado. No requiere montaje FUSE ni permisos de root (a menos que el&lt;br&gt;
destino los requiera). El comando &lt;code&gt;restore&lt;/code&gt; también permite restaurar&lt;br&gt;
archivos del snapshot sin tener que navegar manualmente.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.2 Nivel 2: Restauración por directorio (montaje FUSE)
&lt;/h3&gt;

&lt;p&gt;Para explorar y copiar múltiples archivos sin extraer todo el snapshot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;backup.sh mount aorsrv-20260722_142530
&lt;span class="nb"&gt;ls&lt;/span&gt; /mnt/backup_drive/Backups_linux/mnt/aorsrv-20260722_142530/
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; /mnt/backup_drive/Backups_linux/mnt/aorsrv-20260722_142530/home/aor/ ./recuperado/
backup.sh umount
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El montaje FUSE es de solo lectura. Se pueden usar herramientas&lt;br&gt;
estándar (&lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;rsync&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;) sobre los archivos montados.&lt;br&gt;
Ideal para restaurar directorios enteros sin extraer el snapshot completo&lt;br&gt;
al sistema de archivos.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.3 Nivel 3: Restauración completa del sistema (desastre)
&lt;/h3&gt;

&lt;p&gt;Para recuperar un sistema desde cero tras un fallo catastrófico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# En una instalación limpia de Ubuntu:&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;borgbackup
&lt;span class="c"&gt;# Montar disco externo con el backup&lt;/span&gt;
backup.sh restore-full aorsrv-20260722_142530
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;code&gt;backup.sh&lt;/code&gt; incluye verificación de integridad a tres niveles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Por comando&lt;/strong&gt;: &lt;code&gt;borg check&lt;/code&gt; verifica que todos los chunks son legibles
y que sus checksums coinciden.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Por snapshot&lt;/strong&gt;: &lt;code&gt;backup.sh mount &amp;lt;snap&amp;gt;&lt;/code&gt; y navegación manual
comprueba que los archivos están accesibles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Por repositorio&lt;/strong&gt;: &lt;code&gt;borg info&lt;/code&gt; muestra el ratio de deduplicación, que
sirve como indicador de salud (un ratio anómalo puede indicar
corrupción).&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  7. Decisiones de Diseño
&lt;/h2&gt;
&lt;h3&gt;
  
  
  7.1 ¿Por qué un script y no una herramienta con interfaz?
&lt;/h3&gt;

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

&lt;p&gt;Un solo archivo autocontenido. No hay archivos de configuración externos&lt;br&gt;
que puedan perderse, olvidarse al copiar el script a otro equipo, o&lt;br&gt;
desincronizarse. Se editan 3 variables (&lt;code&gt;BACKUP_BASE&lt;/code&gt;, &lt;code&gt;HOSTNAME&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;PASSPHRASE_FILE&lt;/code&gt;) y el sistema está operativo. La configuración se&lt;br&gt;
exporta con &lt;code&gt;backup.sh export-config&lt;/code&gt; para uso en otros equipos.&lt;/p&gt;
&lt;h3&gt;
  
  
  7.3 ¿Por qué metadatos fuera del repositorio?
&lt;/h3&gt;

&lt;p&gt;Para poder consultar la lista de paquetes, fuentes APT o servicios del&lt;br&gt;
sistema sin tener que montar el repositorio Borg. Si el disco externo&lt;br&gt;
está conectado pero no se quiere (o no se puede) ejecutar Borg, los&lt;br&gt;
metadatos en texto plano son accesibles con &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt; o &lt;code&gt;less&lt;/code&gt;.&lt;br&gt;
Además, proporciona una capa de redundancia: si el repositorio Borg se&lt;br&gt;
corrompe, los metadatos del sistema sobreviven en texto plano.&lt;/p&gt;
&lt;h3&gt;
  
  
  7.4 ¿Por qué &lt;code&gt;repokey&lt;/code&gt; y no &lt;code&gt;keyfile&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;En el modo &lt;code&gt;repokey&lt;/code&gt;, la clave de cifrado viaja dentro del propio&lt;br&gt;
repositorio. No se necesita gestionar un archivo de clave aparte. La&lt;br&gt;
clave está protegida por la frase de paso (PBKDF2), por lo que tener el&lt;br&gt;
repo no basta para descifrarlo. En modo &lt;code&gt;keyfile&lt;/code&gt;, si se pierde el&lt;br&gt;
archivo de clave, el repositorio es irrecuperable aunque se tenga la&lt;br&gt;
frase de paso. &lt;code&gt;repokey&lt;/code&gt; reduce el riesgo de pérdida de clave a cambio&lt;br&gt;
de una protección ligeramente menor (la clave está en el repo, no en un&lt;br&gt;
archivo separado).&lt;/p&gt;
&lt;h3&gt;
  
  
  7.5 ¿Por qué compresión zstd,3?
&lt;/h3&gt;

&lt;p&gt;Zstandard en nivel 3 ofrece la mejor relación compresión/velocidad en&lt;br&gt;
hardware moderno (CPU de los últimos 10 años). Comprime aproximadamente&lt;br&gt;
igual que &lt;code&gt;gzip -6&lt;/code&gt; pero 2-3 veces más rápido. Niveles superiores (10-19)&lt;br&gt;
apenas mejoran la compresión para datos mixtos (binarios + texto) y&lt;br&gt;
ralentizan significativamente el backup. Nivel 3 es el recomendado por&lt;br&gt;
los propios desarrolladores de Borg para uso general.&lt;/p&gt;
&lt;h3&gt;
  
  
  7.6 ¿Por qué capturar colas de logs y no los logs completos?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/var/log/&lt;/code&gt; puede ocupar fácilmente 500 MB o más, y la mayoría del&lt;br&gt;
contenido son líneas antiguas sin valor para una restauración. Capturar&lt;br&gt;
las últimas 200 líneas de los logs del sistema proporciona el contexto&lt;br&gt;
necesario para diagnosticar el estado del sistema en el momento del&lt;br&gt;
backup (errores recientes, arranques, apagados, problemas de red) sin&lt;br&gt;
el peso de almacenar cientos de megabytes de registros históricos que&lt;br&gt;
ya están en el sistema original.&lt;/p&gt;
&lt;h3&gt;
  
  
  7.7 ¿Por qué pre-backup hooks para bases de datos?
&lt;/h3&gt;

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

&lt;p&gt;La alternativa correcta —y la implementada en &lt;code&gt;backup.sh&lt;/code&gt;— es realizar&lt;br&gt;
volcados lógicos (dumps) antes de cada backup:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Motor&lt;/th&gt;
&lt;th&gt;Comando de volcado&lt;/th&gt;
&lt;th&gt;Portable entre versiones&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MySQL/MariaDB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mysqldump --all-databases --single-transaction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pg_dumpall&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mongodump&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SAVE&lt;/code&gt; + copia de dump.rdb&lt;/td&gt;
&lt;td&gt;Parcial (misma versión major)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQLite&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.backup&lt;/code&gt; vía sqlite3&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Ventajas de los dumps frente a copia raw:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Portabilidad:&lt;/strong&gt; 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistencia transaccional:&lt;/strong&gt; &lt;code&gt;mysqldump --single-transaction&lt;/code&gt;
garantiza una instantánea consistente del momento en que comenzó el
dump.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Espacio:&lt;/strong&gt; 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restauración selectiva:&lt;/strong&gt; un dump SQL se puede editar con un editor
de texto para restaurar solo una tabla o una fila.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integridad referencial:&lt;/strong&gt; los dumps preservan claves foráneas,
disparadores, procedimientos almacenados, funciones y vistas en el
orden correcto de creación.&lt;/li&gt;
&lt;/ol&gt;

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

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


&lt;h2&gt;
  
  
  8. Casos de Uso y Escenarios
&lt;/h2&gt;
&lt;h3&gt;
  
  
  8.1 Uso diario (cron)
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 3 * * * /home/aor/bin/backup.sh cron
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./backup.sh doctor         &lt;span class="c"&gt;# Verificar que el sistema está sano&lt;/span&gt;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_BASE&lt;/span&gt;&lt;span class="s2"&gt;/logs/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/backup.log"&lt;/span&gt;  &lt;span class="c"&gt;# Monitorizar resultado&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  8.2 Backup antes de una actualización del sistema
&lt;/h3&gt;

&lt;p&gt;Antes de una operación de riesgo (&lt;code&gt;apt upgrade&lt;/code&gt;, &lt;code&gt;do-release-upgrade&lt;/code&gt;,&lt;br&gt;
cambio de kernel, etc.):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./backup.sh now            &lt;span class="c"&gt;# Backup completo justo antes del cambio&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade           &lt;span class="c"&gt;# Aplicar la actualización&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si la actualización introduce regresiones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./backup.sh diff &amp;lt;snap-pre&amp;gt; &amp;lt;snap-post&amp;gt;   &lt;span class="c"&gt;# Ver qué archivos cambiaron&lt;/span&gt;
./backup.sh restore &amp;lt;snap-pre&amp;gt; etc/hostname /tmp/  &lt;span class="c"&gt;# Recuperar config anterior&lt;/span&gt;
./backup.sh mount &amp;lt;snap-pre&amp;gt;              &lt;span class="c"&gt;# Inspeccionar el sistema antes del cambio&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Escenario: el disco principal falla o se sustituye por uno de mayor&lt;br&gt;
capacidad. El proceso completo con BorgShield:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Conectar disco externo con el backup al nuevo equipo.&lt;/li&gt;
&lt;li&gt;Instalar Ubuntu (o Debian) desde USB. No configurar nada aún.&lt;/li&gt;
&lt;li&gt;Montar disco externo y verificar accesibilidad:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/sdb1 /mnt/backup_drive
mount | &lt;span class="nb"&gt;grep &lt;/span&gt;backup_drive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Copiar backup.sh y ejecutar restore-full:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /mnt/backup_drive/Backups_linux/backup.sh ~/
./backup.sh restore-full &amp;lt;ultimo-snapshot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;El asistente guía paso a paso:

&lt;ul&gt;
&lt;li&gt;Instala Borg si no está presente.&lt;/li&gt;
&lt;li&gt;Pregunta si restaurar fuentes APT (sources.list, GPG keys).&lt;/li&gt;
&lt;li&gt;Ofrece 3 métodos de restauración de paquetes: manual, dpkg-set-selections, apt-clone.&lt;/li&gt;
&lt;li&gt;Pide doble confirmación antes de extraer archivos.&lt;/li&gt;
&lt;li&gt;Muestra tareas post-restauración: hostname, fstab, SSH keys, GRUB.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No es necesario reinstalar el SO desde cero configurándolo primero: los&lt;br&gt;
archivos de configuración del sistema original (resolv.conf, interfaces de&lt;br&gt;
red, fstab, fuentes APT, crontabs, claves SSH) se restauran desde el&lt;br&gt;
backup. Solo el kernel y el cargador de arranque requieren configuración&lt;br&gt;
manual post-restauración (detallada en las tareas post-restauración).&lt;/p&gt;
&lt;h3&gt;
  
  
  8.4 Múltiples equipos en el mismo disco
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/mnt/backup_drive/Backups_linux/
├── borg/portatil/
├── borg/servidor/
├── meta/portatil/
├── meta/servidor/
├── logs/portatil/
└── logs/servidor/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solo es necesario copiar &lt;code&gt;backup.sh&lt;/code&gt; a cada equipo y ajustar&lt;br&gt;
&lt;code&gt;BACKUP_BASE&lt;/code&gt; si es necesario.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Limitaciones y Trabajo Futuro
&lt;/h2&gt;

&lt;h3&gt;
  
  
  9.1 Limitaciones conocidas
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dependencia de BorgBackup&lt;/strong&gt;: el sistema requiere instalar
&lt;code&gt;borgbackup&lt;/code&gt;. En sistemas sin acceso a internet, esto puede ser un
obstáculo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backup remoto no nativo&lt;/strong&gt;: a diferencia de Restic, Borg no tiene
soporte nativo para S3 o Backblaze. Se requiere rclone como capa
adicional.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rendimiento en NTFS&lt;/strong&gt;: aunque Borg funciona sobre NTFS, el
rendimiento puede ser inferior al de ext4 debido a la capa FUSE
(ntfs-3g).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumo de RAM&lt;/strong&gt;: 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker experimental&lt;/strong&gt;: la detección de BBDD dentro de contenedores
Docker está desactivada por defecto (&lt;code&gt;DOCKER_BACKUP=false&lt;/code&gt;) y requiere
que el contenedor tenga las herramientas de dump instaladas.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  9.2 Posibles mejoras
&lt;/h3&gt;

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




&lt;h2&gt;
  
  
  10. Conclusiones
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;backup.sh&lt;/code&gt; resuelve los cuatro problemas fundamentales del backup en&lt;br&gt;
Linux para el escenario de disco externo local:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Eficiencia&lt;/strong&gt;: 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).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fiabilidad&lt;/strong&gt;: los checksums SHA-256 verifican cada byte almacenado.
El comando &lt;code&gt;check --full&lt;/code&gt; garantiza que todos los datos son
recuperables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restaurabilidad&lt;/strong&gt;: tres niveles de restauración (archivo, directorio,
sistema completo) cubren desde la pérdida accidental de un documento
hasta un desastre total. El modo &lt;code&gt;restore-full&lt;/code&gt; guía al usuario paso a
paso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seguridad&lt;/strong&gt;: cifrado AES-256 con frase de paso, archivo de clave con
permisos 600, y disco externo desconectable (protección contra
ransomware).&lt;/li&gt;
&lt;/ol&gt;

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




&lt;h2&gt;
  
  
  11. Diferenciadores Clave Respecto a Otras Soluciones
&lt;/h2&gt;

&lt;p&gt;Más allá de las comparativas cuantitativas (espacio, tiempo, compresión),&lt;br&gt;
&lt;code&gt;backup.sh&lt;/code&gt; introduce &lt;strong&gt;cinco capacidades que no existen juntas en ninguna&lt;br&gt;
otra solución&lt;/strong&gt; del ecosistema Linux:&lt;/p&gt;

&lt;h3&gt;
  
  
  11.1 Restauración virtual (&lt;code&gt;test-restore&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Ninguna herramienta de backup ofrece un comando que verifique la&lt;br&gt;
restaurabilidad semántica de un snapshot sin extraer datos al sistema&lt;br&gt;
de archivos real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;borg check&lt;/strong&gt; verifica integridad técnica (checksums, índices).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;backup.sh test-restore&lt;/strong&gt; 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es el equivalente funcional de &lt;code&gt;tar -tvf&lt;/code&gt; aplicado a todo el ecosistema&lt;br&gt;
de backup: bases de datos, configuración del sistema, logs, paquetes y&lt;br&gt;
archivos.&lt;/p&gt;

&lt;h3&gt;
  
  
  11.2 Dumping automático de BBDD sin configuración
&lt;/h3&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Motor&lt;/th&gt;
&lt;th&gt;backup.sh&lt;/th&gt;
&lt;th&gt;rsync/rsnapshot/timeshift&lt;/th&gt;
&lt;th&gt;Borg puro&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mysqldump&lt;/code&gt; automático&lt;/td&gt;
&lt;td&gt;Copia raw (dañada si mysqld activo)&lt;/td&gt;
&lt;td&gt;Copia raw (dañada)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pg_dumpall&lt;/code&gt; automático&lt;/td&gt;
&lt;td&gt;Copia raw (dañada)&lt;/td&gt;
&lt;td&gt;Copia raw (dañada)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mongodump&lt;/code&gt; automático&lt;/td&gt;
&lt;td&gt;Copia raw (dañada)&lt;/td&gt;
&lt;td&gt;Copia raw (dañada)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SAVE&lt;/code&gt; + RDB&lt;/td&gt;
&lt;td&gt;Copia raw&lt;/td&gt;
&lt;td&gt;Copia raw&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No requiere configurar credenciales, hooks ni scripts externos. Detecta&lt;br&gt;
el motor por &lt;code&gt;pgrep&lt;/code&gt; + &lt;code&gt;command -v&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  11.3 Metadatos completos del sistema en cada snapshot
&lt;/h3&gt;

&lt;p&gt;Cada snapshot contiene 14 categorías de metadatos que van mucho más allá&lt;br&gt;
de lo que cualquier herramienta de backup captura:&lt;/p&gt;

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

&lt;p&gt;Esto significa que, con un solo snapshot, se puede reconstruir el perfil&lt;br&gt;
completo de software del sistema original sin necesidad de tener el&lt;br&gt;
sistema funcionando.&lt;/p&gt;

&lt;h3&gt;
  
  
  11.4 Restauración guiada interactiva
&lt;/h3&gt;

&lt;p&gt;Mientras que Borg, restic y rsync ofrecen &lt;code&gt;extract&lt;/code&gt;/&lt;code&gt;restore&lt;/code&gt; como&lt;br&gt;
comandos planos, &lt;code&gt;restore-full&lt;/code&gt; implementa un &lt;strong&gt;asistente paso a paso&lt;/strong&gt;&lt;br&gt;
que:&lt;/p&gt;

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

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

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

&lt;p&gt;Es la herramienta ideal para verificar el contenido de un snapshot antes de&lt;br&gt;
comprometerse con una restauración real.&lt;/p&gt;

&lt;h3&gt;
  
  
  11.5 Arquitectura autocontenida
&lt;/h3&gt;

&lt;p&gt;A diferencia de las soluciones que requieren:&lt;/p&gt;

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

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

&lt;h3&gt;
  
  
  11.6 Reporte de archivos excluidos
&lt;/h3&gt;

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

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

&lt;h3&gt;
  
  
  11.7 Captura de repositorios git, entornos de desarrollo y configuración de usuario
&lt;/h3&gt;

&lt;p&gt;Cada snapshot incluye, además de los archivos del sistema, metadatos&lt;br&gt;
estructurados sobre el perfil de usuario:&lt;/p&gt;

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

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

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

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

&lt;p&gt;&lt;strong&gt;Configuración del escritorio&lt;/strong&gt; (&lt;code&gt;meta/dconf_dump.txt&lt;/code&gt;):&lt;br&gt;
&lt;code&gt;dconf dump /&lt;/code&gt; produce texto plano con toda la configuración del&lt;br&gt;
entorno de escritorio (GNOME, Unity, etc.). Restaurable con&lt;br&gt;
&lt;code&gt;dconf load / &amp;lt; meta/dconf_dump.txt&lt;/code&gt;.&lt;/p&gt;

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

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

&lt;p&gt;&lt;strong&gt;Conexiones NetworkManager&lt;/strong&gt; (&lt;code&gt;meta/nm_connections.txt&lt;/code&gt;):&lt;br&gt;
resumen legible de conexiones de red configuradas. Los archivos reales&lt;br&gt;
están en &lt;code&gt;/etc/NetworkManager/system-connections/&lt;/code&gt; (respaldados).&lt;/p&gt;

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

&lt;p&gt;Esto resuelve los problemas clásicos en restauraciones:&lt;/p&gt;

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

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




&lt;h2&gt;
  
  
  12. Gestión de Dependencia: BorgBackup
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;backup.sh&lt;/code&gt; depende de BorgBackup. Si Borg cambia su CLI, formato de&lt;br&gt;
salida o flags, el script puede fallar.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.1 Verificación post-actualización
&lt;/h3&gt;

&lt;p&gt;El script incluye &lt;code&gt;check_borg_compat()&lt;/code&gt; que verifica automáticamente que&lt;br&gt;
la versión instalada de Borg soporte todas las opciones utilizadas.&lt;br&gt;
Esta función se ejecuta:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;En &lt;code&gt;cmd_now()&lt;/code&gt; antes de cada backup (bloqueante: si falta algo, aborta).&lt;/li&gt;
&lt;li&gt;En &lt;code&gt;cmd_doctor()&lt;/code&gt; como diagnóstico (informativo: muestra advertencias).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;backup.sh doctor          &lt;span class="c"&gt;# Diagnóstico completo (incluye compatibilidad)&lt;/span&gt;
backup.sh verify          &lt;span class="c"&gt;# Verificar passphrase&lt;/span&gt;
backup.sh test-restore &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;backup.sh list | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-2&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  12.2 Puntos de fallo conocidos
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  12.4 Lecciones aprendidas: bugs cazados durante el desarrollo
&lt;/h3&gt;

&lt;p&gt;Durante las sesiones de desarrollo y shellcheck del script, se&lt;br&gt;
identificaron y corrigieron varios bugs sutiles relacionados con el uso&lt;br&gt;
de &lt;code&gt;set -e&lt;/code&gt; y operadores bash:&lt;/p&gt;

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

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

&lt;h3&gt;
  
  
  12.5 Prácticas recomendadas
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Ejecutar &lt;code&gt;backup.sh doctor&lt;/code&gt; tras cada &lt;code&gt;apt upgrade borgbackup&lt;/code&gt; para
verificar que &lt;code&gt;check_borg_compat()&lt;/code&gt; no detecta incompatibilidades.&lt;/li&gt;
&lt;li&gt;Mantener copia del script en el disco de backup (no solo en el
sistema).&lt;/li&gt;
&lt;li&gt;Si Borg cambia su formato de repo, el repo existente sigue siendo
legible por versiones anteriores — no actualizar Borg sin verificar.&lt;/li&gt;
&lt;li&gt;Usar &lt;code&gt;backup.sh test-restore &amp;lt;ultimo-snapshot&amp;gt;&lt;/code&gt; tras cada actualización
para verificar que la restauración sigue funcionando.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  13. Borg es el Taladro, backup.sh es el Robot — El Valor del Sistema Completo
&lt;/h2&gt;

&lt;p&gt;BorgBackup es el motor, pero nosotros construimos un sistema completo&lt;br&gt;
orquestado alrededor. Esto es lo que aportamos:&lt;/p&gt;

&lt;h3&gt;
  
  
  13.1 Automatización de backup completo
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  13.2 Metadatos del sistema (lo que hace restaurable el backup)
&lt;/h3&gt;

&lt;p&gt;Borg solo guarda archivos. Nosotros capturamos el estado del sistema&lt;br&gt;
completo en cada snapshot:&lt;/p&gt;

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

&lt;p&gt;Sin esto, restaurar un sistema desde un backup de Borg te deja con&lt;br&gt;
archivos, pero no sabes QUÉ instalar, QUÉ configurar, CÓMO reconstruir.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.3 Cuatro niveles de restauración
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;restore-dry-run&lt;/code&gt;&lt;/strong&gt; — simulación completa sin modificar nada del sistema.
Muestra paso a paso qué comandos se ejecutarían, qué paquetes/paquetes
manuales/snaps/flatpaks/git/VMs se restaurarían. No requiere root.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;restore &amp;lt;ruta&amp;gt;&lt;/code&gt;&lt;/strong&gt; — restaurar archivo/directorio específico&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;test-restore&lt;/code&gt;&lt;/strong&gt; — validar el backup (equivalente a &lt;code&gt;tar -tvf&lt;/code&gt; para
TODO el ecosistema: BBDD, metadatos, rutas esenciales)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;restore-full&lt;/code&gt;&lt;/strong&gt; — asistente interactivo que guía al usuario paso a
paso: fuentes apt, paquetes, BBDD, git, configuraciones&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  13.4 Seguridad y robustez
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verificación de compatibilidad de Borg&lt;/strong&gt; (&lt;code&gt;check_borg_compat&lt;/code&gt;) —
detecta si una opción no está disponible en la versión instalada&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protección contra &lt;code&gt;set -e&lt;/code&gt;&lt;/strong&gt; — cazamos y corregimos bugs silenciosos
que mataban el script&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shellcheck limpio&lt;/strong&gt; — 0 warnings (más de 3000 líneas de bash)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Función &lt;code&gt;list_snapshots()&lt;/code&gt;&lt;/strong&gt; — lista snapshots numerados en todos los comandos interactivos (restore, mount, diff, restore-full, restore-dry-run, test-restore)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validación de rutas en &lt;code&gt;rm -rf&lt;/code&gt;&lt;/strong&gt; — todas empiezan con path literal,
nunca con variable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dry-run mode&lt;/strong&gt; — &lt;code&gt;DRY_RUN=true&lt;/code&gt; verifica sin ejecutar nada&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  13.5 Arquitectura lista para producción
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Rotación de logs, compactación post-prune, notificaciones por correo&lt;/li&gt;
&lt;li&gt;Lock para evitar ejecuciones concurrentes&lt;/li&gt;
&lt;li&gt;Modo cron (no interactivo, sin colores, solo log)&lt;/li&gt;
&lt;li&gt;Configurable vía vars editables en el script&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  13.6 En resumen
&lt;/h3&gt;

&lt;p&gt;Borg es el taladro. Nosotros construimos el robot que sabe qué agujeros&lt;br&gt;
hacer, cuándo, con qué broca, y deja un informe de cada agujero. Sin&lt;br&gt;
nosotros, el usuario tendría que escribir los comandos Borg manualmente,&lt;br&gt;
saber qué incluir/excluir, mantener los scripts de backup de BBDD, y no&lt;br&gt;
tendría metadatos para restaurar — solo archivos sueltos.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. Consideraciones de Seguridad al Publicar Métricas
&lt;/h2&gt;

&lt;p&gt;BorgShield recolecta una cantidad inusualmente alta de metadatos del&lt;br&gt;
sistema. Esto es una ventaja para la restauración, pero introduce&lt;br&gt;
&lt;strong&gt;riesgos de exposición&lt;/strong&gt; si se publican métricas detalladas del&lt;br&gt;
entorno real.&lt;/p&gt;

&lt;h3&gt;
  
  
  14.1 Exposición de identidad y huella del sistema
&lt;/h3&gt;

&lt;p&gt;Publicar métricas exactas (kernel, número de paquetes, versiones&lt;br&gt;
específicas) permite a un atacante:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identificar CVEs aplicables a una versión exacta de kernel o paquetes.&lt;/li&gt;
&lt;li&gt;Perfilar el hardware y software del sistema objetivo.&lt;/li&gt;
&lt;li&gt;Reducir el espacio de búsqueda de vulnerabilidades.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mitigación:&lt;/strong&gt; usar rangos (&lt;code&gt;~360 GB&lt;/code&gt;, &lt;code&gt;~3200 paquetes&lt;/code&gt;, &lt;code&gt;Kernel 5.15.x&lt;/code&gt;)&lt;br&gt;
en lugar de valores exactos.&lt;/p&gt;

&lt;h3&gt;
  
  
  14.2 Metadatos fuera del repositorio
&lt;/h3&gt;

&lt;p&gt;Los metadatos en &lt;code&gt;meta/&lt;/code&gt; (logs, paquetes, usuarios, dconf, GPG) están&lt;br&gt;
en &lt;strong&gt;texto plano sin cifrar&lt;/strong&gt; en el disco de backup. A diferencia del&lt;br&gt;
repositorio Borg (AES-256), cualquiera con acceso físico al disco puede&lt;br&gt;
leer esta carpeta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mitigación:&lt;/strong&gt; usar cifrado a nivel de disco (LUKS, BitLocker) en el&lt;br&gt;
disco de backup, o tratar la carpeta &lt;code&gt;meta/&lt;/code&gt; con la confidencialidad&lt;br&gt;
de un log del sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  14.3 Captura de logs sin filtrar
&lt;/h3&gt;

&lt;p&gt;Las 200 últimas líneas de syslog, auth.log, kern_log, etc. se capturan&lt;br&gt;
sin filtrar IPs ni nombres de usuario. Si el disco no está cifrado,&lt;br&gt;
estos logs son legibles en texto plano.&lt;/p&gt;

&lt;h3&gt;
  
  
  14.4 Dumps temporales de bases de datos
&lt;/h3&gt;

&lt;p&gt;Los volcados SQL residen en &lt;code&gt;/var/backups/pre-backup-hooks/&lt;/code&gt; durante&lt;br&gt;
la ejecución del backup. Si el script se interrumpe antes de limpiar,&lt;br&gt;
los dumps quedan en disco principal en formato legible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mitigación:&lt;/strong&gt; el script limpia el directorio al inicio de cada backup&lt;br&gt;
(&lt;code&gt;rm -rf "${pre_dir_name:?}/"*&lt;/code&gt;), no al final. Un fallo antes de la&lt;br&gt;
limpieza deja los dumps del backup anterior intactos. Verificar el log&lt;br&gt;
tras cada ejecución.&lt;/p&gt;




&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;BorgBackup Documentation. &lt;a href="https://borgbackup.readthedocs.io/" rel="noopener noreferrer"&gt;https://borgbackup.readthedocs.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Zstandard Compression Algorithm. &lt;a href="https://facebook.github.io/zstd/" rel="noopener noreferrer"&gt;https://facebook.github.io/zstd/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Rsync Project. &lt;a href="https://rsync.samba.org/" rel="noopener noreferrer"&gt;https://rsync.samba.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Restic Project. &lt;a href="https://restic.net/" rel="noopener noreferrer"&gt;https://restic.net/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ntfs-3g FUSE Driver. &lt;a href="https://www.tuxera.com/community/open-source-ntfs-3g/" rel="noopener noreferrer"&gt;https://www.tuxera.com/community/open-source-ntfs-3g/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;RSnapshot. &lt;a href="https://rsnapshot.org/" rel="noopener noreferrer"&gt;https://rsnapshot.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Debian Administrator's Handbook. &lt;a href="https://debian-handbook.info/" rel="noopener noreferrer"&gt;https://debian-handbook.info/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ubuntu Server Guide - Backups. &lt;a href="https://ubuntu.com/server/docs/backups" rel="noopener noreferrer"&gt;https://ubuntu.com/server/docs/backups&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Apéndice A: Glosario
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Término&lt;/th&gt;
&lt;th&gt;Definición&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BorgBackup&lt;/td&gt;
&lt;td&gt;Software de backup con deduplicación, compresión y cifrado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chunk&lt;/td&gt;
&lt;td&gt;Bloque de datos de tamaño variable (64 KiB-1 MiB) en que Borg divide los archivos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deduplicación&lt;/td&gt;
&lt;td&gt;Almacenamiento de un solo bloque idéntico aunque aparezca en múltiples archivos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FUSE&lt;/td&gt;
&lt;td&gt;Filesystem in Userspace — permite montar un snapshot como directorio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardlink&lt;/td&gt;
&lt;td&gt;Múltiples entradas de directorio apuntando al mismo inodo (datos)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HMAC&lt;/td&gt;
&lt;td&gt;Hash-based Message Authentication Code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NTFS-3G&lt;/td&gt;
&lt;td&gt;Controlador NTFS en espacio de usuario (FUSE)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PBKDF2&lt;/td&gt;
&lt;td&gt;Password-Based Key Derivation Function — función lenta para derivar clave de una frase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prune&lt;/td&gt;
&lt;td&gt;Eliminación automática de snapshots según política de retención&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;repokey&lt;/td&gt;
&lt;td&gt;Modo de cifrado donde la clave se almacena dentro del repositorio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snapshot&lt;/td&gt;
&lt;td&gt;Instantánea del sistema en un momento dado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zstandard&lt;/td&gt;
&lt;td&gt;Algoritmo de compresión moderno con niveles de 1 a 22&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Apéndice B: Comandos Borg Útiles (uso avanzado)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ver cambios entre dos snapshots&lt;/span&gt;
borg diff /ruta/repo::snap1::snap2

&lt;span class="c"&gt;# Exportar un snapshot a otro repositorio&lt;/span&gt;
borg transfer /ruta/repo1 /ruta/repo2

&lt;span class="c"&gt;# Crear un repo desde cero (avanzado)&lt;/span&gt;
borg init &lt;span class="nt"&gt;--encryption&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;repokey-blake2 /ruta/repo

&lt;span class="c"&gt;# Ver el espacio ocupado por archivos temporales&lt;/span&gt;
borg list /ruta/repo &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{path}{NL}'&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Exportar snapshot como tar (para enviar a otro sistema)&lt;/span&gt;
borg export-tar /ruta/repo::snapshot /tmp/backup.tar

&lt;span class="c"&gt;# Recuperar una copia de la clave del repositorio&lt;/span&gt;
borg key &lt;span class="nb"&gt;export&lt;/span&gt; /ruta/repo backup-key.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Apéndice C: Crontab recomendado
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# MIN HOUR DAY MONTH WEEK COMMAND
# Backup diario a las 3:00 AM
0 3 * * * /home/aor/bin/backup.sh cron &amp;gt;/dev/null 2&amp;gt;&amp;amp;1

# Verificación rápida semanal (domingo 5:00)
0 5 * * 0 /home/aor/bin/backup.sh check &amp;gt;/dev/null 2&amp;gt;&amp;amp;1

# Verificación completa mensual (1er domingo del mes 6:00)
0 6 1-7 * 0 /home/aor/bin/backup.sh check --full &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Salida:&lt;/strong&gt; toda la salida se redirige a &lt;code&gt;/dev/null&lt;/code&gt; para evitar correos&lt;br&gt;
de cron innecesarios. Los resultados se registran en el log de backup.&lt;/p&gt;

</description>
      <category>borgbackup</category>
      <category>linux</category>
      <category>backup</category>
      <category>devops</category>
    </item>
    <item>
      <title>Generar epub desde una lista de ficheros html</title>
      <dc:creator>Arcadio Ortega Reinoso</dc:creator>
      <pubDate>Wed, 15 Jul 2026 08:59:30 +0000</pubDate>
      <link>https://dev.to/arcadio_ortega/generar-epub-desde-una-lista-de-ficheros-html-4lel</link>
      <guid>https://dev.to/arcadio_ortega/generar-epub-desde-una-lista-de-ficheros-html-4lel</guid>
      <description>&lt;h1&gt;
  
  
  Desde html hasta epub
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Ejemplos de libros que he generado desde mis páginas html
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://archive.org/details/ai-ia-inteligencia-artificial-aplicada" rel="noopener noreferrer"&gt;AI - IA. Inteligencia artificial aplicada a la programación y la docencia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://archive.org/details/nube-privada-integral/" rel="noopener noreferrer"&gt;Nube privada virtual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://archive.org/details/dns_20260703" rel="noopener noreferrer"&gt;Manual Técnico: servidor DNS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;En &lt;code&gt;https://github.com/aortrei469/epubDesdeHTML&lt;/code&gt; se encuentra el software al que se hace referencia en el artículo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Generar epub desde una relación de ficheros html
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;HACER COPIA DE SEGURIDAD DE TODO ANTES DE EMPEZAR&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Cambiamos el contenido del &amp;lt;head&amp;gt; de todos los ficheros html que formarán parte del epub
&lt;/h4&gt;

&lt;p&gt;Dejamos, como ejemplo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;XXXXX&amp;lt;/title&amp;gt;
    &amp;lt;meta charset="UTF-8" /&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&amp;gt;
    &amp;lt;meta name="author" content="XXXXXXXXXXXXXXX" /&amp;gt;
    &amp;lt;meta name="robots" content="noindex, nofollow" /&amp;gt;
    &amp;lt;link rel="stylesheet" href="css/manual.css" type="text/css" media="all" /&amp;gt;
&amp;lt;/head&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Purgar todo aquello que no se pueda encontrar en el epub, por ejemplo en mi caso tengo que Eliminar todos los &amp;lt;a&amp;gt; que engloban a las &amp;lt;img&amp;gt; en las &amp;lt;figure&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Utilidad:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aor@aorsrv:~/proyectos/opencode/epubHtmlToEpub$ ls *.sh
eliminaTagASobreTagImg.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ejemplo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aor@aorsrv:~/proyectos/opencode/epubHtmlToEpub/libro$ ../eliminaTagASobreTagImg.sh 
Procesando: 0_Infraestructura.html
Procesando: 1_srv01.html
Procesando: 2_srv01_maquinas_virtuales.html
Procesando: 3_SRV01_mv_database.html
Procesando: 4_SRV01_mv_grafana_loki.html
Procesando: 5_SRV01_mv_openproject.html
Procesando: 6_srv01_n8n.html
Procesando: 7_wordpress.html
Hecho. Backups creados como *.bak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  También tendré problemas con los grafos. Buscamos los &amp;lt;div class="mermaid"&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Eliminamos del  lo siguiente&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script&amp;gt;
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            securityLevel: 'loose',
            flowchart: { useMaxWidth: true, htmlLabels: true },
            sequence: { useMaxWidth: true }
        });
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Así como todos los scripts que estemos usando. Es mejor no usarlos, es sólo&lt;br&gt;
documentación.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Para mermaid generamos también la imagen y según sea para html o epub lo&lt;br&gt;
seleccionaremos mediante estilo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ejemplo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.mermaid {
    display: none !important;
}

.img-mermaid {
    display: block !important;
}   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Cambiarle el css para que corte tablas, código etc.
&lt;/h4&gt;

&lt;p&gt;Usamos el css que tenemos preparado para los ebooks. Esto es,&lt;br&gt;
&lt;code&gt;resultadoBaseEpubEnMIsDocumentos.css&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
...

/* ==========================================================================
   8. PAGINACIÓN Y CONTROL DE SALTOS (Reglas Kindle)
   ========================================================================== */
h1, h2, h3 {
    page-break-after: avoid;
}
figure, .diagram-container, table, pre {
    page-break-inside: avoid;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;En epub por ejemplo no se pueden usar atributos como &lt;em&gt;align&lt;/em&gt; , por lo que lo&lt;br&gt;
trabajamos mediante clases&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/*
ya no se puede usar align
*/
.texto-centrado {
    text-align: center;
}
.texto-derecha {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Limpiar metadatas
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sudo apt install mat2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;find ./libro/images/ -type f -exec mat2 --inplace {} +&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Vemos los errores obtenidos, y los solucionamos&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Verificar que no quedan metadatos
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sudo apt install libimage-exiftool-perl&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;find ./libro/images/ -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -exec sh -c 'echo "=== Examinando: $1 ==="; exiftool "$1" | grep -E "Camera|Date|Software|Modify|Create|Artist|Copyright"' _ {} \;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;(En una sola imagen: exiftool imagen.jpg.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Verificamos que no tengamos espacios en blanco en nombres de ficheros
&lt;/h4&gt;

&lt;p&gt;Para saber si hay ficheros que no cumplen ejecutamos:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ cat verificar_epub.sh 
#!/bin/bash

# Comprobar si se ha pasado un directorio como argumento
if [ -z "$1" ]; then
    echo "Uso: $0 /ruta/al/directorio/del/epub"
    exit 1
fi

TARGET_DIR="$1"

# Verificar si el directorio existe
if [ ! -d "$TARGET_DIR" ]; then
    echo "Error: El directorio '$TARGET_DIR' no existe."
    exit 1
fi

echo "Iniciando verificación de nombres de archivo en: $TARGET_DIR"
echo "--------------------------------------------------------"

ALERTA=0

# Buscar todos los archivos de forma recursiva
while IFS= read -r -d '' archivo; do
    # Obtener solo el nombre del archivo (sin la ruta)
    nombre=$(basename "$archivo")
    # Obtener la ruta relativa desde el directorio objetivo
    ruta_relativa="${archivo#$TARGET_DIR/}"

    # 1. Exclusión del archivo mimetype en la raíz (es una excepción válida)
    if [ "$ruta_relativa" == "mimetype" ]; then
        continue
    fi

    # 2. Verificar caracteres no permitidos (solo permite A-Z, a-z, 0-9, ., _, -)
    if [[ ! "$nombre" =~ ^[A-Za-z0-9._-]+$ ]]; then
        echo "[ERROR] Caracteres inválidos o espacios en: $ruta_relativa"
        ALERTA=1
    fi

    # 3. Verificar longitud del nombre del archivo (máximo 255 bytes)
    if [ ${#nombre} -gt 255 ]; then
        echo "[ERROR] Nombre demasiado largo (&amp;gt;255 caracteres): $ruta_relativa"
        ALERTA=1
    fi

done &amp;lt; &amp;lt;(find "$TARGET_DIR" -type f -print0)

echo "--------------------------------------------------------"
if [ $ALERTA -eq 0 ]; then
    echo "¡Éxito! Todos los archivos cumplen con las restricciones de EPUB."
else
    echo "Se han encontrado errores. Corrige los nombres antes de compilar el EPUB."
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ejemplo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ ./verificar_epub.sh libro
Iniciando verificación de nombres de archivo en: libro
--------------------------------------------------------
[ERROR] Caracteres inválidos o espacios en: images/wordpress/Captura de pantalla_2025-11-21_19-06-12.jpg
[ERROR] Caracteres inválidos o espacios en: images/wordpress/Captura de pantalla_2025-11-21_19-05-41.jpg
[ERROR] Caracteres inválidos o espacios en: images/wordpress/Captura de pantalla_2025-11-21_19-02-49.jpg
[ERROR] Caracteres inválidos o espacios en: images/wordpress/Captura de pantalla_2025-11-21_19-04-55.jpg
[ERROR] Caracteres inválidos o espacios en: images/wordpress/Captura de pantalla_2025-11-21_19-04-41.jpg
[ERROR] Caracteres inválidos o espacios en: images/wordpress/Captura de pantalla_2025-11-21_19-03-30.jpg
[ERROR] Caracteres inválidos o espacios en: images/wordpress/Captura de pantalla_2025-11-21_19-04-26.jpg
--------------------------------------------------------
Se han encontrado errores. Corrige los nombres antes de compilar el EPUB.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Generamos el libro
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source env/bin/activate
./env/bin/python generar_epub.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Chequeamos el libro generado
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;sudo apt install epubcheck&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;epubcheck libro.epub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Una vez que lo tenemos (hasta entonces: eliminar epub, regenerar, volver a&lt;br&gt;
chequear&lt;/p&gt;

&lt;h4&gt;
  
  
  Actualizamos los errores encontrados en nuestro ficheros htm originales
&lt;/h4&gt;

&lt;p&gt;Si los hemos conservado. HACER COPIA DE SEGURIDAD ANTES DE EMPEZAR&lt;/p&gt;

&lt;h4&gt;
  
  
  Vamos a minificar nuestros documentos
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;sudo apt install -y minify&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minify -r --html-keep-conditional-comments --match=".*\.(html|xhtml|css)$" -o libro/ libro_min/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ejemplo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ mkdir libro_min
(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ minify -r --html-keep-conditional-comments --match=".*\.(html|xhtml|css)$" -o libro_min libro
(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ ls libro
0_Infraestructura.html  2_srv01_maquinas_virtuales.html  4_SRV01_mv_grafana_loki.html  6_srv01_n8n.html  css
1_srv01.html            3_SRV01_mv_database.html         5_SRV01_mv_openproject.html   7_wordpress.html  images
(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ ls libro_min/
libro
(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ ls libro_min/libro/
0_Infraestructura.html  2_srv01_maquinas_virtuales.html  4_SRV01_mv_grafana_loki.html  6_srv01_n8n.html  css
1_srv01.html            3_SRV01_mv_database.html         5_SRV01_mv_openproject.html   7_wordpress.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Verificamos el resultado &lt;strong&gt;Y volvemos a generar el libro minimizado&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ rm -f libro.epub 
(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ ./env/bin/python generar_epub.py
Páginas HTML: 8
CSS:          1
Imágenes:     42
  ✓ 0_Infraestructura.html → 0_Infraestructura.xhtml  (NUBE PRIVADA INTEGRAL)
  ✓ 1_srv01.html → 1_srv01.xhtml  (Server01)
  ✓ 2_srv01_maquinas_virtuales.html → 2_srv01_maquinas_virtuales.xhtml  (Server01. MVs)
  ✓ 3_SRV01_mv_database.html → 3_SRV01_mv_database.xhtml  (database)
  ✓ 4_SRV01_mv_grafana_loki.html → 4_SRV01_mv_grafana_loki.xhtml  (observability)
  ✓ 5_SRV01_mv_openproject.html → 5_SRV01_mv_openproject.xhtml  (OpenProject)
  ✓ 6_srv01_n8n.html → 6_srv01_n8n.xhtml  (n8n)
  ✓ 7_wordpress.html → 7_wordpress.xhtml  (wordpress)

 EPUB generado: libro.epub
    ID: xxxxxxxxxxxx
(env) aor@aorsrv:~/proyectos/opencode/epubDesdeHtml$ epubcheck libro.epub
Validación usando la versión de reglas epub 3.2.
No se han detectado errores o advertencias.
Mensajes: 0 errores fatales / 0 errores / 0 advertencias / 0 indicaciones

EPUBCheck completado
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Cargamos en Sigil
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/Descargas$ ./Sigil-2.7.6-x86_64.AppImage 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Y hacemos:&lt;/p&gt;

&lt;h4&gt;
  
  
  Herramientas
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;MUY IMPORTANTE HAY QUE HACER TODOS LOS PASOS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Editar metadatos&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Añadir portada&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reformatear HTML&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comprobar epub F7&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Complementos
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Edición -&amp;gt; Baka-jpeg&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El plugin Baka-Jpeg para Sigil tiene como objetivo comprimir y reducir el&lt;br&gt;
tamaño de las imágenes en tu archivo ePub, tomando decisiones inteligentes.&lt;br&gt;&lt;br&gt;
El plugin procesa formatos como JPG, BMP y PNG, y en el caso de los PNG, &lt;strong&gt;los&lt;br&gt;
convierte a JPEG si determina que esto reducirá significativamente el tamaño&lt;br&gt;
del archivo (por ejemplo, en fotografías o imágenes complejas)&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Recomendación: tener solo jpg en las páginas html antes de iniciar el&lt;br&gt;
proceso&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tener en cuenta:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Para textos o dibujos: El plugin es "inteligente" e intenta evitar comprimir archivos PNG que contienen texto nítido, ya que pasarlos a JPEG puede hacer que se vean borrosos.&lt;/li&gt;
&lt;li&gt;Conversión: Sí, puede transformar imágenes PNG a JPG para optimizar el peso total del libro electrónico.&lt;/li&gt;
&lt;li&gt;Recomendación: Como este tipo de plugins modifica los archivos de forma permanente, siempre se aconseja hacer una copia de seguridad o guardar tu archivo ePub antes de ejecutarlo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El plugin realiza todo el proceso en tres pasos internos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conversión: Transforma el archivo físico de la imagen de .png a .jpeg.&lt;/li&gt;
&lt;li&gt;Actualización del código: Busca todas las etiquetas &amp;lt;img src="..."&amp;gt; en tus archivos HTML y cambia la extensión .png por .jpeg para que sigan apuntando al archivo correcto.&lt;/li&gt;
&lt;li&gt;Actualización del Manifiesto: Modifica el archivo de control del ePub (content.opf) para registrar el nuevo formato de imagen. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tras usarlo verificar que todo queda correcto, hacer una búsqueda por&lt;br&gt;
ejemplo de todos los .png&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>html2epub</category>
    </item>
    <item>
      <title>pensamiento computacional</title>
      <dc:creator>Arcadio Ortega Reinoso</dc:creator>
      <pubDate>Thu, 02 Jul 2026 17:08:18 +0000</pubDate>
      <link>https://dev.to/arcadio_ortega/pensamiento-computacional-13ig</link>
      <guid>https://dev.to/arcadio_ortega/pensamiento-computacional-13ig</guid>
      <description></description>
    </item>
    <item>
      <title>Pensamiento Computacional: Una Herramienta Mental para el Siglo XXI</title>
      <dc:creator>Arcadio Ortega Reinoso</dc:creator>
      <pubDate>Thu, 02 Jul 2026 17:02:23 +0000</pubDate>
      <link>https://dev.to/arcadio_ortega/pensamiento-computacional-una-herramienta-mental-para-el-siglo-xxi-3ahk</link>
      <guid>https://dev.to/arcadio_ortega/pensamiento-computacional-una-herramienta-mental-para-el-siglo-xxi-3ahk</guid>
      <description>&lt;p&gt;El &lt;strong&gt;Pensamiento Computacional (PC)&lt;/strong&gt; ha emergido no solo como una disciplina técnica, sino como un &lt;strong&gt;proceso mental humano&lt;/strong&gt; fundamental para resolver problemas, diseñar sistemas y comprender el comportamiento humano a través de los conceptos de la informática. Lejos de limitarse al aprendizaje de la programación, se considera hoy una &lt;strong&gt;habilidad analítica básica&lt;/strong&gt;, tan crucial como la lectura, la escritura o la aritmética.&lt;/p&gt;

&lt;h3&gt;
  
  
  Los Cuatro Pilares del Pensamiento Computacional
&lt;/h3&gt;

&lt;p&gt;El núcleo del PC se sostiene sobre cuatro capacidades cognitivas esenciales que permiten abordar la complejidad de manera estructurada:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Descomposición:&lt;/strong&gt; Consiste en la habilidad de &lt;strong&gt;fragmentar un problema complejo en partes más pequeñas&lt;/strong&gt; y manejables, facilitando que cada pieza sea comprendida y solucionada de forma independiente.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Reconocimiento de Patrones:&lt;/strong&gt; Es el proceso de identificar &lt;strong&gt;tendencias o regularidades&lt;/strong&gt; dentro de los problemas, lo que permite aplicar soluciones ya conocidas a nuevos subproblemas similares.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Abstracción:&lt;/strong&gt; Considerada la &lt;strong&gt;esencia del PC&lt;/strong&gt;, implica centrarse exclusivamente en la información relevante, &lt;strong&gt;ignorando los detalles innecesarios&lt;/strong&gt; para crear modelos simplificados de la realidad.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Pensamiento Algorítmico:&lt;/strong&gt; La capacidad de diseñar una &lt;strong&gt;serie de pasos ordenados e instrucciones precisas&lt;/strong&gt; para alcanzar una solución ejecutable por un humano o una máquina.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  La Dimensión Cognitiva: Pensar Rápido y Despacio
&lt;/h3&gt;

&lt;p&gt;La integración de la psicología cognitiva en el PC, basada en el modelo de Daniel Kahneman, revela que esta disciplina requiere un esfuerzo consciente del &lt;strong&gt;Sistema 2 (Pensamiento Lento)&lt;/strong&gt;. Mientras que el Sistema 1 opera de forma intuitiva y rápida, el PC exige actividades deliberadas para &lt;strong&gt;decomponer programas grandes&lt;/strong&gt; o analizar la complejidad de los datos, evitando así los sesgos y errores del pensamiento automático.&lt;/p&gt;

&lt;p&gt;Para estructurar este pensamiento, se recurre a menudo al &lt;strong&gt;Método de Pólya&lt;/strong&gt;, una secuencia lógica de cuatro pasos: comprender el problema, elaborar un plan, ejecutarlo y, finalmente, realizar una &lt;strong&gt;revisión retrospectiva y metacognitiva&lt;/strong&gt; de la solución.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debates y Paradigmas Educativos
&lt;/h3&gt;

&lt;p&gt;A pesar de su expansión, el campo del PC enfrenta desacuerdos fundamentales sobre su naturaleza y enseñanza:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;¿Proceso Mental o Práctica Social?&lt;/strong&gt; Algunos expertos definen el PC puramente como una capacidad cognitiva individual. Otros proponen la &lt;strong&gt;"Acción Computacional"&lt;/strong&gt;, argumentando que el aprendizaje es más efectivo cuando los estudiantes crean proyectos con un &lt;strong&gt;impacto real en su comunidad&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;¿Independiente de la Programación?&lt;/strong&gt; Existe un debate sobre si la programación es el &lt;strong&gt;vehículo indispensable&lt;/strong&gt; o si el PC puede desarrollarse como un proceso de pensamiento independiente de la tecnología específica.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Implementación Curricular:&lt;/strong&gt; Las estrategias oscilan entre la &lt;strong&gt;integración transversal&lt;/strong&gt; en materias como ciencias o matemáticas y la creación de una &lt;strong&gt;materia específica&lt;/strong&gt; de informática para asegurar el rigor.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Del Entendimiento Profundo a la Creación Empoderada
&lt;/h3&gt;

&lt;p&gt;Para distinguir entre un estudiante que ha memorizado definiciones y uno que posee un &lt;strong&gt;entendimiento profundo&lt;/strong&gt;, es necesario evaluar la aplicación de conceptos en contextos nuevos. Un experto en PC no solo sabe que un algoritmo "funciona", sino que evalúa su &lt;strong&gt;eficiencia&lt;/strong&gt; y es capaz de realizar una &lt;strong&gt;transferencia de conceptos&lt;/strong&gt; a tareas cotidianas no tecnológicas. En última instancia, el objetivo es transformar al individuo de un &lt;strong&gt;consumidor pasivo a un creador empoderado&lt;/strong&gt; que utiliza la tecnología para generar cambios significativos en el mundo.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bibliografía de Referencia
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Bordignon, F., &amp;amp; Iglesias, A. A. (2020).&lt;/strong&gt; &lt;em&gt;Introducción al pensamiento computacional&lt;/em&gt;. Ciudad Autónoma de Buenos Aires: UNIPE; Editorial Universitaria; EDUCAR S.E..&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Chun, B., &amp;amp; Piotrowski, T. (2023).&lt;/strong&gt; &lt;em&gt;Pensamiento computacional ilustrado: Una guía de dibujos animados para solucionar problemas, diseñar sistemas y comprender el comportamiento humano&lt;/em&gt;. Eduteka / ctiillustrated.com.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Kiwelekar, A. W., Navandar, S., &amp;amp; Yadav, D. K. (2020).&lt;/strong&gt; &lt;em&gt;A Two-Systems Perspective for Computational Thinking&lt;/em&gt;. Proceedings of 12th International Conference on Intelligent Human Interaction (IHCI 2020). Springer.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Kong, S. C., &amp;amp; Abelson, H. (Eds.). (2019).&lt;/strong&gt; &lt;em&gt;Computational Thinking Education&lt;/em&gt;. Springer Nature Singapore Pte Ltd..&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Al-Fedaghi, S., &amp;amp; Alkhaldi, A. A. (2019).&lt;/strong&gt; &lt;em&gt;Thinging for Computational Thinking&lt;/em&gt;. Kuwait University, Computer Engineering Department. Vol. 10, No. 2.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>pensamientocomputacional</category>
      <category>problemsolving</category>
      <category>innovacióneducativa</category>
    </item>
    <item>
      <title>Actuando sobre la Seguridad Perimetral: Cómo Implementar un Cortafuegos Dinámico basado en el Comportamiento DNS</title>
      <dc:creator>Arcadio Ortega Reinoso</dc:creator>
      <pubDate>Fri, 12 Jun 2026 11:33:22 +0000</pubDate>
      <link>https://dev.to/arcadio_ortega/actuando-sobre-la-seguridad-perimetral-como-implementar-un-cortafuegos-dinamico-basado-en-el-4844</link>
      <guid>https://dev.to/arcadio_ortega/actuando-sobre-la-seguridad-perimetral-como-implementar-un-cortafuegos-dinamico-basado-en-el-4844</guid>
      <description>

&lt;p&gt;En el panorama actual de la ciberseguridad, los métodos tradicionales de filtrado a menudo se quedan cortos ante usuarios que utilizan VPNs, túneles o servidores DNS externos para evadir políticas corporativas. Para abordar este reto, he desarrollado un ecosistema de dos herramientas complementarias: &lt;strong&gt;Network Sniffer&lt;/strong&gt; y &lt;strong&gt;DNS Traffic Controller&lt;/strong&gt;, diseñadas para transformar la navegación de los usuarios en reglas de firewall inteligentes y en tiempo real.&lt;/p&gt;

&lt;h3&gt;
  
  
  El Concepto: "Si no hay consulta DNS, no hay tráfico"
&lt;/h3&gt;

&lt;p&gt;La filosofía central de esta solución es la visibilidad total. La idea base consiste en &lt;strong&gt;capturar todas las peticiones DNS de la red y actuar sobre cualquier dirección IP que no haya sido obtenida mediante una resolución previa&lt;/strong&gt;. Este enfoque de "lista blanca dinámica" asegura que los dispositivos no puedan conectarse a IPs "hardcodeadas" o servidores maliciosos que intenten saltarse la resolución estándar del sistema.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Fase de Análisis: Network Sniffer
&lt;/h3&gt;

&lt;p&gt;Antes de bloquear, es vital entender el tráfico. &lt;strong&gt;Network Sniffer&lt;/strong&gt; es una herramienta para Ubuntu que permite capturar y clasificar las conexiones entrantes y salientes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Captura Inteligente:&lt;/strong&gt; Utiliza &lt;code&gt;tcpdump&lt;/code&gt; para monitorizar consultas DNS y &lt;code&gt;Scapy&lt;/code&gt; para el análisis de paquetes, extrayendo metadatos clave como el SNI (Server Name Indication) incluso en tráfico cifrado TLS.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Clasificación de Riesgo Offline:&lt;/strong&gt; Una de sus mayores ventajas es que realiza un análisis 100% offline de amenazas utilizando bases de datos como Spamhaus DROP y MaxMind GeoLite2.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Generación de Blocklists:&lt;/strong&gt; Tras el análisis (ya sea en tiempo real o mediante consulta posterior a logs JSON/TXT), la herramienta puede exportar listas de bloqueo automáticas en formatos compatibles con MikroTik, &lt;code&gt;iptables&lt;/code&gt;, DNSMasq y BIND.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Fase de Control: DNS Traffic Controller
&lt;/h3&gt;

&lt;p&gt;Una vez definido el comportamiento deseado, &lt;strong&gt;DNS Traffic Controller&lt;/strong&gt; se encarga de la ejecución de las reglas. Esta herramienta ofrece dos modos de operación según la infraestructura necesaria.&lt;/p&gt;

&lt;h4&gt;
  
  
  Modo Router (Filtro Perimetral)
&lt;/h4&gt;

&lt;p&gt;Es la solución ideal para una empresa. Actúa como un gateway/router usando &lt;code&gt;ipset&lt;/code&gt; e &lt;code&gt;iptables&lt;/code&gt; para una eficiencia máxima.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Proxy DNS Transparente:&lt;/strong&gt; Intercepta todas las queries DNS (puerto 53) y las redirige a un proxy local.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Autorización Dinámica:&lt;/strong&gt; Cuando un usuario consulta un dominio legítimo, el sistema obtiene las IPs resueltas y las añade automáticamente al conjunto &lt;code&gt;dns_allowed&lt;/code&gt; de &lt;code&gt;ipset&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Filtrado Estricto:&lt;/strong&gt; El firewall permite el tráfico solo hacia las IPs presentes en ese conjunto, bloqueando todo lo demás de forma predeterminada.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Bloqueos Avanzados y Evasión
&lt;/h4&gt;

&lt;p&gt;Para evitar que los usuarios salten el muro, el sistema incluye reglas específicas para denegar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;DNS Externos y Cifrados:&lt;/strong&gt; Bloquea DNS sobre TLS (puerto 853), DoH (DoH-block) y el uso de QUIC/HTTP3 (puerto 443 UDP).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;VPNs y Túneles:&lt;/strong&gt; Detecta y bloquea protocolos de VPN conocidos (OpenVPN, WireGuard, IPsec) y herramientas de tunelización como &lt;code&gt;ngrok&lt;/code&gt; o Cloudflare Tunnel.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Contenido No Deseado:&lt;/strong&gt; Incluye soporte para listas negras de control parental, educativo y dominios sospechosos.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Integración en el Flujo de Trabajo Empresarial
&lt;/h3&gt;

&lt;p&gt;Este conjunto de herramientas permite establecer un ciclo de seguridad cerrado:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Monitorización con Network Sniffer:&lt;/strong&gt; Se analizan los patrones de navegación para identificar qué dominios son necesarios para la actividad empresarial.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Establecimiento de la Entrada del Firewall:&lt;/strong&gt; Con los datos capturados, se configura el &lt;strong&gt;DNS Traffic Controller&lt;/strong&gt; para que actúe como la barrera de entrada, permitiendo solo lo estrictamente resuelto mediante el DNS corporativo.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Auditoría y Refinamiento:&lt;/strong&gt; Se generan informes periódicos (en HTML o JSON) para ajustar las listas negras y blancas, detectando posibles intentos de conexión a países de alto riesgo (como KP, IR o SY) o puertos sospechosos de troyanos.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Fortalezas técnicas para destacar en el artículo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Eficiencia con &lt;code&gt;ipset&lt;/code&gt;:&lt;/strong&gt; En el modo &lt;strong&gt;Router Controller&lt;/strong&gt;, el uso de &lt;code&gt;ipset&lt;/code&gt; es un factor diferencial. Permite manejar grandes listas de IPs permitidas o bloqueadas sin degradar el rendimiento del firewall, algo crucial para entornos empresariales con mucho tráfico.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Análisis 100% Offline:&lt;/strong&gt; Es un gran argumento de venta para la privacidad. &lt;strong&gt;Network Sniffer&lt;/strong&gt; realiza geolocalización (MaxMind) y detección de amenazas (Spamhaus DROP) de forma local, evitando que los metadatos de la empresa salgan a APIs externas durante el análisis.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Detección de Evasión Avanzada:&lt;/strong&gt; Tus herramientas no solo filtran por IP/Dominio; también están preparadas para bloquear &lt;strong&gt;DNS sobre TLS (puerto 853)&lt;/strong&gt;, &lt;strong&gt;QUIC/HTTP3 (puerto 443 UDP)&lt;/strong&gt; y herramientas de tunelización como &lt;strong&gt;ngrok&lt;/strong&gt; o &lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;, que son los métodos habituales para saltarse firewalls tradicionales.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Modo "Deep" para Auditoría:&lt;/strong&gt; El &lt;strong&gt;Network Sniffer&lt;/strong&gt; en su modo profundo aporta un valor forense importante al incluir resolución PTR, WHOIS y detección de proveedores de Cloud/Hosting, lo que permite a un administrador saber exactamente quién es el dueño de la infraestructura a la que se conectan sus usuarios.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Versatilidad de Exportación e Integración:&lt;/strong&gt; Una de las mayores ventajas de este ecosistema es su capacidad para convertir el análisis de red en reglas ejecutables de forma casi instantánea. &lt;strong&gt;Network Sniffer&lt;/strong&gt; no solo identifica amenazas, sino que permite exportar automáticamente listas de bloqueo (blocklists) en formatos nativos para las infraestructuras más comunes. Esto incluye scripts &lt;strong&gt;.rsc para MikroTik&lt;/strong&gt;, configuraciones de zona para &lt;strong&gt;BIND&lt;/strong&gt; y &lt;strong&gt;Unbound&lt;/strong&gt;, directivas para &lt;strong&gt;DNSMasq&lt;/strong&gt;, así como reglas de filtrado para &lt;strong&gt;iptables&lt;/strong&gt; o formatos universales como &lt;strong&gt;archivos Hosts y CSV&lt;/strong&gt;. Esta interoperabilidad garantiza que la inteligencia de seguridad generada pueda integrarse sin fricciones en firewalls y servidores DNS ya existentes, permitiendo a los administradores ajustar el nivel de restricción según un umbral de riesgo personalizado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Al combinar la capacidad de análisis profundo de &lt;strong&gt;Network Sniffer&lt;/strong&gt; con el control dinámico de &lt;strong&gt;DNS Traffic Controller&lt;/strong&gt;, las organizaciones pueden pasar de un modelo de seguridad pasivo a uno proactivo. Ya no se trata solo de bloquear lo conocido como malo, sino de permitir únicamente lo que el sistema ha validado previamente a través de una consulta legítima.&lt;/p&gt;

&lt;p&gt;Si quieres explorar el código o contribuir al proyecto, ambos repositorios están disponibles en mi perfil de GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/aortrei469/dns-traffic-controller" rel="noopener noreferrer"&gt;dns-traffic-controller&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/aortrei469/network-sniffer" rel="noopener noreferrer"&gt;network-sniffer&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>cybersecurity</category>
      <category>dns</category>
      <category>firewall</category>
      <category>perimetral</category>
    </item>
    <item>
      <title>La Nueva Abstracción de la Ingeniería de Software y la Crisis Educativa de la Sintaxis</title>
      <dc:creator>Arcadio Ortega Reinoso</dc:creator>
      <pubDate>Wed, 10 Jun 2026 10:24:11 +0000</pubDate>
      <link>https://dev.to/arcadio_ortega/la-nueva-abstraccion-de-la-ingenieria-de-software-y-la-crisis-educativa-de-la-sintaxis-2b46</link>
      <guid>https://dev.to/arcadio_ortega/la-nueva-abstraccion-de-la-ingenieria-de-software-y-la-crisis-educativa-de-la-sintaxis-2b46</guid>
      <description>&lt;h3&gt;
  
  
  La Nueva Abstracción: El Programador como Arquitecto en la Era de la IA
&lt;/h3&gt;

&lt;p&gt;La historia de la ingeniería de software es una crónica de la huida constante hacia niveles superiores de abstracción. Así como en décadas pasadas el programador dejó de preocuparse por el lenguaje máquina o el ensamblador para enfocarse en lenguajes de alto nivel, hoy asistimos a un nuevo desplazamiento de la "caja negra". La Inteligencia Artificial actúa ahora como un "lubricante" que traduce la lógica conceptual directamente en código ejecutable, permitiendo que el profesional se sitúe mucho más cerca de los requerimientos que de la sintaxis. Sin embargo, a pesar de este "superpoder" de implementación, los cimientos de los problemas clásicos de la disciplina permanecen inalterados.&lt;/p&gt;

&lt;h4&gt;
  
  
  La Crisis Permanente y el "Qué" sobre el "Cómo"
&lt;/h4&gt;

&lt;p&gt;A pesar de las herramientas modernas, el fracaso en los proyectos suele tener una raíz sociotécnica más que técnica. Los problemas clásicos de definición —donde el cliente rara vez sabe lo que quiere con precisión— siguen siendo el principal obstáculo. La IA puede generar código de manera impecable, pero si el análisis de requisitos es vago o erróneo, la máquina construirá a la perfección el producto equivocado. Este dilema subraya la persistencia de la &lt;strong&gt;Validación&lt;/strong&gt; (¿estamos construyendo lo que el usuario realmente necesita?) como un desafío puramente humano.&lt;/p&gt;

&lt;h4&gt;
  
  
  La IA como Lubricante de la Implementación
&lt;/h4&gt;

&lt;p&gt;En la fase de construcción, la IA ha venido a mitigar fricciones históricas que consumían gran parte del tiempo del desarrollador:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Fin del "Infierno de la Sintaxis":&lt;/strong&gt; Reduce el tiempo perdido buscando documentación o resolviendo problemas de sintaxis triviales.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Explicación de Código Ajeno:&lt;/strong&gt; Facilita la comprensión de "código espagueti" o sistemas heredados, eliminando el miedo a tocar módulos antiguos (el síndrome del código huérfano).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Automatización de Pruebas:&lt;/strong&gt; Al generar suites de pruebas unitarias con rapidez, ayuda a combatir el síndrome de "en mi máquina funciona" y reduce los fallos de integración.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Refactorización:&lt;/strong&gt; Permite limpiar estructuras rígidas y reducir la deuda técnica en segundos, algo que tradicionalmente tomaba horas de rediseño.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Los Nuevos Riesgos: Código Zombi y Deuda Técnica
&lt;/h4&gt;

&lt;p&gt;No obstante, esta facilidad conlleva peligros. La capacidad de generar código masivo sin un entendimiento profundo puede derivar en "código zombi": sistemas que funcionan pero cuya lógica interna nadie comprende realmente. Esto no elimina la deuda técnica, sino que la transforma en una forma más insidiosa de complejidad que puede superar la capacidad cognitiva humana a medida que el sistema crece.&lt;/p&gt;

&lt;h4&gt;
  
  
  El Cambio de Paradigma en la Enseñanza y el Rol Profesional
&lt;/h4&gt;

&lt;p&gt;Bajo este escenario, el programador deja de ser un "escribano" para convertirse en un &lt;strong&gt;revisor y arquitecto&lt;/strong&gt;. La enseñanza de la informática debe evolucionar desde la enseñanza de la sintaxis hacia la gestión de la complejidad y la comunicación. Los objetivos pedagógicos actuales deben centrarse en:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Ingeniería de Requisitos y Contexto:&lt;/strong&gt; Aprender a alimentar a los modelos con la información correcta (Ingeniería del Contexto) para obtener resultados precisos.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Verificación y Validación (V&amp;amp;V):&lt;/strong&gt; Priorizar la capacidad de supervisar si el producto cumple con las especificaciones y satisface al usuario.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Metodologías Híbridas:&lt;/strong&gt; Implementar flujos de trabajo donde humanos y agentes colaboren bajo marcos ágiles como &lt;strong&gt;Scrumban&lt;/strong&gt;. El uso de agentes (como CrewAI) permite automatizar la implementación mientras el humano se centra en la dirección estratégica y el flujo de valor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Concluyendo: Aunque la "caja negra" de la implementación sea ahora más grande y eficiente, la esencia de la ingeniería de software sigue siendo la traducción de ideas abstractas en productos funcionales. El éxito en este nuevo paradigma no depende de la velocidad de codificación, sino de la precisión en la definición y la rigurosidad en la validación del sistema resultante.&lt;/p&gt;

&lt;p&gt;¿Qué opinas? Si eres docente o estudiante, ¿crees que los centros educativos están reaccionando a tiempo a este cambio de paradigma? ¿Estamos preparados para evaluar a "arquitectos" en lugar de a "escribanos" de código? Espero leer tu perspectiva en los comentarios.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwaredevelopment</category>
      <category>career</category>
    </item>
    <item>
      <title>Aula Informática compartida, eficiente y centralizada con Linux</title>
      <dc:creator>Arcadio Ortega Reinoso</dc:creator>
      <pubDate>Wed, 03 Sep 2025 15:21:11 +0000</pubDate>
      <link>https://dev.to/arcadio_ortega/aula-informatica-compartida-eficiente-y-centralizada-con-linux-425e</link>
      <guid>https://dev.to/arcadio_ortega/aula-informatica-compartida-eficiente-y-centralizada-con-linux-425e</guid>
      <description>&lt;p&gt;&lt;strong&gt;Cómo Construir un Aula Informática Eficiente y Centralizada con Linux&lt;/strong&gt;&lt;br&gt;
La gestión de un aula informática con múltiples estaciones de trabajo puede ser una tarea desafiante. Mantener la consistencia del sistema, gestionar las cuentas de usuario, y asegurar el espacio en disco son solo algunas de las preocupaciones comunes. Afortunadamente, con herramientas de código abierto como NIS, LDAP, NFS y Autofs, podemos construir una solución robusta y fácil de administrar.&lt;br&gt;
Recientemente he consolidado una guía detallada para configurar un entorno de aula informática centralizado en un repositorio de GitHub, donde los estudiantes pueden iniciar sesión en cualquier máquina cliente con sus cuentas y directorios personales gestionados desde un servidor central&lt;br&gt;
. El objetivo es mantener una configuración consistente en las máquinas cliente y gestionar eficazmente el uso de recursos&lt;/p&gt;

&lt;p&gt;Las tecnologías clave empleadas en esta configuración para lograr un entorno gestionado centralmente incluyen:&lt;br&gt;
• Servicio de Información de Red (NIS) o Protocolo Ligero de Acceso a Directorios (LDAP): Estos servicios son fundamentales para centralizar la gestión de cuentas de usuario y grupo. Permiten que los usuarios se autentiquen en cualquier máquina cliente, facilitando el inicio de sesión único y la administración de credenciales&lt;/p&gt;

&lt;p&gt;• Sistema de Archivos de Red (NFS): Utilizado para compartir los directorios personales de los usuarios (/home) desde el servidor central. De esta manera, los datos de los estudiantes están siempre accesibles, sin importar en qué estación de trabajo inicien sesión&lt;/p&gt;

&lt;p&gt;• Autofs: Complementa a NFS al montar automáticamente los directorios personales de los usuarios solo cuando se accede a ellos, optimizando el uso de recursos al evitar montar todos los directorios al inicio del sistema&lt;/p&gt;

&lt;p&gt;• Cuotas de Disco: Implementadas para limitar el espacio en disco y la cantidad de archivos que cada usuario puede utilizar en su directorio personal, gestionado en el servidor NFS. Esto es crucial para un uso equitativo de los recursos&lt;/p&gt;

&lt;p&gt;• Congelación del Sistema (bilibop-lockfs): Una característica poderosa para mantener el sistema operativo de las máquinas cliente en un estado inmutable. Cualquier cambio realizado durante una sesión se descarta al reiniciar, lo que asegura una configuración limpia y consistente en cada uso&lt;/p&gt;

&lt;p&gt;• Scripts y Programación (Cron): Para automatizar la creación de usuarios y facilitar el proceso de actualización de los sistemas congelados, minimizando la intervención manual&lt;/p&gt;

&lt;p&gt;El resultado es un aula informática donde los usuarios disfrutan de una experiencia consistente en cualquier estación de trabajo, sus datos se guardan de forma centralizada y los recursos se gestionan eficientemente, mientras que el estado base de las estaciones de trabajo se mantiene siempre idéntico&lt;/p&gt;

&lt;p&gt;Si estás interesado en implementar una configuración similar o simplemente quieres profundizar en los pasos de instalación y configuración de cada uno de estos componentes, he detallado todo el proceso en mi repositorio de GitHub. Allí encontrarás las instrucciones paso a paso para servidores y clientes, así como scripts de ejemplo y verificaciones esenciales&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/aortrei469/aula-compartida" rel="noopener noreferrer"&gt;aula-compartida&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Este artículo se basa en la documentación "Aula de informática" de Arcadio Ortega Reinoso, bajo licencia CC BY-NC-SA 4.0&lt;/p&gt;

</description>
      <category>nis</category>
      <category>nfs</category>
      <category>autofs</category>
      <category>computerlab</category>
    </item>
  </channel>
</rss>
