Estrategia de backup para servidores root que aguanta cuando hace falta
La regla 3-2-1 en un único servidor root, restic y Borg con ejemplos, retención y cifrado. Y el paso que casi todo el mundo se salta: probar de verdad la restauración.
La checklist para los primeros 30 minutos termina con un archivo tar de /etc y con la constatación de que eso todavía no es un backup, sino una copia en el mismo disco. Justo ahí arranca este artículo: cómo convertirlo en una estrategia que sobreviva a una pérdida total.
La frase alrededor de la que gira todo: un backup del que nunca se ha recuperado nada no es un backup, es una esperanza. Todo lo demás sirve para convertir esa esperanza en un hecho comprobado.
Todos los comandos se ejecutan como root. Si trabajas como usuario normal, antepón sudo a cada comando. Los sistemas de referencia son Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS y Ubuntu 22.04 LTS. Donde los cuatro se diferencian, se indica en el punto correspondiente.
Antes de cambiar nada: el camino de vuelta
El backup en sí rara vez se rompe. Lo peligroso es todo lo que se hace a su alrededor: una restauración que escribe encima del sistema en marcha, un repositorio que llena el disco del sistema, archivos de claves que sustituyen tu propio acceso. Cuatro puntos antes de empezar.
1. Conoce el acceso por consola antes de necesitarlo
En los servidores root KVM y en los servidores dedicados de KernelHost tienes la consola VNC en el área de cliente. No depende del stack de red del sistema invitado y sigue respondiendo aunque SSH ya no diga nada. Ese es el camino de rescate cuando una restauración ha escrito una sshd_config o una authorized_keys antiguas encima de las actuales. Entra por ahí una vez antes de necesitarlo y comprueba que te sabes la contraseña de root.
2. Nunca restaures directamente a / en el primer intento
La primera restauración va siempre a un directorio vacío, por ejemplo /var/tmp/restore-test. Desde ahí comparas y copias de vuelta solo lo que necesitas. Restaurar directamente en / sobrescribe también los archivos que han cambiado desde el backup por un buen motivo.
3. Mantén una segunda sesión abierta
Mientras trabajes con claves SSH o con la authorized_keys del destino, vale la misma regla que al montar un firewall: deja abierto un segundo terminal con una conexión establecida y ciérralo solo cuando una conexión nueva funcione.
4. Comprueba el espacio antes de que crezca el repositorio
df -h /
df -i /
La segunda línea se le olvida a casi todo el mundo: un sistema de archivos también se llena cuando todavía quedan gigabytes libres, en concreto cuando se acaban los inodos. Un repositorio local que llena el disco del sistema es una de las averías autoinfligidas más frecuentes. Por eso, aquí el destino está fuera del servidor desde el primer momento.
La regla 3-2-1 aplicada a un solo servidor
- Tres copias. Los datos de producción son ya la primera copia. Hacen falta, por tanto, dos backups y no uno.
- Dos soportes distintos. Dos directorios en el mismo disco son un solo soporte, y dos discos en el mismo RAID también: un
rmpor descuido alcanza a los dos. El RAID protege contra el fallo de una unidad y contra nada más. - Una copia fuera de casa. Ni el mismo servidor, ni la misma cuenta de gestión, e idealmente tampoco la misma ubicación.
Hacen falta dos añadidos. Primero, una copia debería estar donde el propio servidor no pueda borrarla, porque quien se haga con tu servidor encontrará ahí las credenciales de acceso al destino. Segundo, una copia solo cuenta cuando se ha comprobado. Una imagen del sistema en la misma área de cliente es cómoda, pero como copia fuera de casa no cuenta.
Fija además dos cifras: cuántas horas de pérdida de datos puedes asumir (eso determina el intervalo entre dos ejecuciones) y cuánto puede durar la restauración (eso decide si además necesitas una imagen del sistema).
Qué entra en el backup y qué no
El error más frecuente no es respaldar demasiado poco, sino respaldarlo todo. Quien copia / entero sin exclusiones se lleva de paso las cachés de paquetes, los archivos temporales y la swap.
| Qué | Ubicación típica | Método | Por qué |
|---|---|---|---|
| Configuración | /etc | Backup de archivos | Reconstruirla a mano cuesta días |
| Selección de paquetes | Archivo de texto, ver más abajo | Backup de archivos | Hace reproducible la reinstalación |
| Datos de aplicación | /var/www, /srv, /home | Backup de archivos | No se pueden volver a conseguir |
| Bases de datos | /var/lib/mysql | Dump en lugar de copia de archivos | Las copias de archivos en caliente son inconsistentes |
| Certificados | /etc/letsencrypt | Backup de archivos | Clave de la cuenta y límites de emisión de la autoridad de certificación |
| Contenedores | Archivos Compose y volúmenes | Backup de archivos | Las imágenes se vuelven a descargar, los volúmenes no |
| No respaldar | /proc, /sys, /dev, /run, /tmp | excluir | Interfaces del kernel sin contenido de archivo |
| No respaldar | /var/cache, swap | excluir | Se pueden regenerar en cualquier momento |
apt-mark showmanual > /root/lista-paquetes.txt
dpkg --get-selections > /root/seleccion-paquetes.txt
wc -l /root/lista-paquetes.txt /root/seleccion-paquetes.txt
apt-mark showmanual lista solo los paquetes instalados de forma expresa, sin las dependencias que vinieron con ellos: la lista corta que necesitas al reconstruir el servidor.
Archivos, base de datos e imagen: tres métodos que no se sustituyen entre sí
| Método | Protege bien contra | No protege contra | Trampa típica |
|---|---|---|---|
| Backup de archivos | Borrados, archivos sueltos dañados, pérdida del servidor | La inconsistencia de bases de datos abiertas | Copiar de paso los archivos de la base de datos en caliente |
| Backup de base de datos (dump) | La inconsistencia, volver a un estado limpio | Todo lo que está fuera de la base de datos | Un dump interrumpido cuyo archivo parece válido |
| Imagen del sistema | La caída total, un tiempo de restauración corto | Un borrado que se detecta tarde, la pérdida de la cuenta | Pocos estados y todos en la misma cuenta |
De ahí sale un orden, no una elección. Primero el servidor de bases de datos escribe un dump, después se ejecuta el backup de archivos y el directorio de datos queda excluido. Una copia de archivos de /var/lib/mysql en caliente captura distintas tablas en distintos momentos. Si se deja restaurar o no, lo descubrirás en el peor momento posible.
El archivo de credenciales, los permisos y las trampas del dump los trata Backup diario de bases de datos MySQL en Debian, Ubuntu y Linux. Lo importante es el punto de entrega: los dumps aterrizan en /var/backups/db, se quedan ahí uno o dos días y de la retención se encarga el repositorio. PostgreSQL lo respaldas con pg_dumpall como usuario postgres.
restic o Borg
Los dos parten los archivos en bloques, guardan una sola vez los bloques idénticos, cifran y almacenan estados versionados. Los dos están empaquetados en las cuatro distribuciones. La diferencia que decide está en la última fila.
| Característica | restic | Borg |
|---|---|---|
| Paquete | restic | borgbackup, comando borg |
| Cifrado | siempre activo | opcional, conviene repokey o keyfile |
| Liberar espacio | forget con --prune | prune y después compact |
| Protección contra el borrado por parte del servidor | servidor REST o almacenamiento de objetos con versionado | borg serve --append-only |
| Requisito en el destino | basta con un acceso SFTP | Borg tiene que estar instalado en el destino |
En un almacenamiento donde no puedes instalar nada, Borg queda descartado. Si dispones de un segundo servidor Linux bajo tu gestión, el modo append-only juega a favor de Borg.
Configurarlo con restic
apt update
apt install -y restic
restic version
Revisa la salida antes de crear un repositorio: las cuatro distribuciones entregan versiones muy distintas, y un repositorio escrito por una versión más nueva no siempre se deja abrir con una más antigua.
Acceso al destino
El destino es aquí un segundo servidor al que se llega por SSH. La clave pertenece a root, porque solo root puede leer todos los archivos que hay que respaldar:
ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519_backup -C 'backup srv01'
ssh-copy-id -i /root/.ssh/id_ed25519_backup.pub backup@203.0.113.50
cat > /root/.ssh/config <<'EOF'
Host destino-backup
HostName 203.0.113.50
User backup
IdentityFile /root/.ssh/id_ed25519_backup
BatchMode yes
EOF
chmod 600 /root/.ssh/config
Comprobación: ssh destino-backup true termina sin salida y sin ninguna pregunta. La primerísima conexión pregunta por la clave del host: respóndela ahora y no más tarde dentro de un servicio que no puede esperar a nadie.
Contraseña y repositorio
install -d -m 700 /etc/restic
head -c 32 /dev/urandom | base64 | tr -d '\n' > /etc/restic/repo.pass
chmod 600 /etc/restic/repo.pass
cat > /etc/restic/env <<'EOF'
RESTIC_REPOSITORY=sftp:destino-backup:/srv/backup/srv01
RESTIC_PASSWORD_FILE=/etc/restic/repo.pass
EOF
chmod 600 /etc/restic/env
Este archivo sirve igual para la shell y para systemd. En la shell:
set -a; . /etc/restic/env; set +a
restic init
Comprobación: restic cat config muestra una estructura JSON corta con el identificador del repositorio. Si aparece la pregunta Is there a repository at the following location?, la ruta no es correcta o restic init no se ha ejecutado nunca.
La primera ejecución
cat > /etc/restic/excludes.txt <<'EOF'
/proc
/sys
/dev
/run
/tmp
/var/tmp
/var/cache
/var/lib/apt/lists
/var/lib/mysql
/swapfile
EOF
restic backup / --one-file-system --exclude-file=/etc/restic/excludes.txt --exclude-caches --tag system
--one-file-system mantiene el backup dentro del sistema de archivos raíz y deja fuera las unidades de red montadas. --exclude-caches se salta los directorios que se han marcado a sí mismos como caché. Excluir /var/lib/mysql es la puesta en práctica del apartado anterior.
Comprobación: la ejecución termina con una línea del tipo snapshot 0a1b2c3d saved. Después:
restic snapshots
restic stats latest
En la lista aparecen la fecha, el nombre del host y las rutas. Si restic stats latest muestra un tamaño sospechosamente pequeño, alguna exclusión va demasiado lejos.
Lo mismo con Borg
apt install -y borgbackup
borg --version
export BORG_REPO='ssh://backup@203.0.113.50/./srv01'
borg init --encryption=repokey-blake2
borg create --stats --compression zstd ::'system-{now}' /etc /var/www /home /var/backups
borg list
borg info
Las cuatro distribuciones entregan una versión de la serie 1.x. Borg tiene que estar presente en los dos lados, y la versión del destino no debería ser más antigua que la del servidor. Usa un repositorio propio por servidor: así te ahorras tener que limitar la limpieza a los archivos de ese servidor en concreto y puedes trabajar con claves de acceso separadas.
Comprobación: borg list muestra el archivo con su marca de tiempo, y borg info el tamaño antes y después de la deduplicación.
Retención: más larga de lo que casi todo el mundo calcula
El tiempo de retención no depende de cuánto quieras conservar los datos, sino de cuánto tarda en notarse un daño. Un directorio borrado se nota el mismo día, una tabla dañada muchas veces varias semanas después. Quien guarda siete días tendrá entonces siete días de backups con el daño ya dentro.
| Tipo de datos | Propuesta | Motivo |
|---|---|---|
| Dumps de bases de datos | 7 diarios, 4 semanales, 6 mensuales | Los daños silenciosos se notan tarde |
| Configuración | 30 diarios, 12 mensuales | Poder reconstruir cuándo cambió qué |
| Datos de aplicación | 30 diarios, 6 mensuales | Los archivos borrados rara vez se echan en falta enseguida |
| Logs | tan poco tiempo como sea razonable | Ocupan mucho y casi nunca hacen falta para restaurar |
restic forget --dry-run --keep-daily 7 --keep-weekly 4 --keep-monthly 6
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
La pasada en seco muestra qué estados desaparecerían. Sin --prune solo se van las referencias y el espacio sigue ocupado. En Borg esto es de dos pasos desde la 1.2, y el segundo comando olvidado explica la mayoría de los repositorios que no quieren encoger:
borg prune --list --dry-run --keep-daily=7 --keep-weekly=4 --keep-monthly=6
borg prune --list --keep-daily=7 --keep-weekly=4 --keep-monthly=6
borg compact
Comprobación: restic snapshots o borg list muestran el escalonado esperado, y el tamaño ocupado en el destino baja.
El cifrado y la clave que después ya no tiene nadie
Las dos herramientas cifran antes de que los datos salgan del servidor. El destino solo ve bloques ilegibles, que es lo que hace aceptable un almacenamiento ajeno. El precio está claro: sin la contraseña o sin la clave, los datos están perdidos para siempre. No hay ninguna puerta trasera.
De ahí salen dos reglas. Primera: la contraseña tiene que estar en un segundo sitio, normalmente en un gestor de contraseñas. Una contraseña que solo vive en /etc/restic/repo.pass desaparece con el servidor, y con ella el backup. Segunda: en Borg con repokey, exporta la clave y guárdala fuera, porque en ese modo vive dentro del propio repositorio:
borg key export ::
Comprobación: ejecuta restic snapshots en otro equipo con la contraseña sacada del gestor de contraseñas. Una contraseña que nunca has usado desde otro sitio está sin confirmar.
Proteger el destino contra el borrado
Un atacante con permisos de root también tiene acceso a la contraseña guardada y a la clave del destino, así que puede borrar el backup antes de cifrar los datos de producción. Por eso hace falta un almacenamiento que acepte estados nuevos pero no permita borrar nada. En Borg lo configuras en la authorized_keys del usuario de backup en el destino:
command="borg serve --append-only --restrict-to-path /srv/backup/srv01",restrict ssh-ed25519 AAAA... backup srv01
A partir de ahí, la clave solo acepta backups y únicamente en esa ruta. Cuenta con que un prune se ejecutará hasta el final sin liberar espacio, porque el borrado no llega a realizarse en el destino. La limpieza la haces allí donde el servidor no tiene acceso. En restic asumen ese papel el servidor REST en modo append-only o un almacenamiento de objetos con versionado. Un acceso SFTP a secas no da para eso.
Automatizarlo con un timer de systemd
Un timer es preferible a un cronjob porque escribe la salida en el journal, recupera las ejecuciones que se hayan perdido y puede repartir la hora de arranque. Sobre cómo se construyen las units: Crear un servicio systemd propio y ejecutarlo automáticamente al iniciar el sistema.
cat > /etc/systemd/system/backup.service <<'EOF'
[Unit]
Description=Backup diario con restic
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/restic/env
Nice=10
IOSchedulingClass=idle
ExecStart=/usr/bin/restic backup / --one-file-system --exclude-file=/etc/restic/excludes.txt --exclude-caches --tag system
ExecStart=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
EOF
cat > /etc/systemd/system/backup.timer <<'EOF'
[Unit]
Description=Inicia el backup diario
[Timer]
OnCalendar=*-*-* 02:30:00
RandomizedDelaySec=1800
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable --now backup.timer
systemd-analyze calendar '*-*-* 02:30:00'
Varias líneas ExecStart dentro de una unit oneshot se ejecutan una detrás de otra, y un fallo corta la cadena. La limpieza solo se ejecuta, por tanto, después de un backup que ha salido bien. Si el destino es un sistema de archivos montado, hace falta un seguro por delante, porque si no la ejecución escribe sin que nadie lo note dentro del punto de montaje vacío:
ExecStartPre=/usr/bin/mountpoint -q /mnt/backup
Comprobación:
systemctl start backup.service
systemctl list-timers backup.timer
journalctl -u backup.service -n 50 --no-pager
systemctl list-timers tiene que indicar una próxima hora de arranque. Si ahí no aparece nada, el timer no está activado. El punto más importante viene al final: una ejecución que deja de ejecutarse en silencio es la forma normal en la que fallan los backups. Comprueba systemctl is-failed backup.service, o añade como última línea ExecStart una llamada a un servicio de monitorización externo que dé la alarma cuando falte la señal de vida diaria.
Probar la restauración
La prueba pequeña, cada mes, cinco minutos
mkdir -p /var/tmp/restore-test
restic restore latest --target /var/tmp/restore-test --include /etc/ssh/sshd_config
diff /etc/ssh/sshd_config /var/tmp/restore-test/etc/ssh/sshd_config && echo "idéntico"
Con Borg va igual, y guarda las rutas sin la barra inicial:
cd /var/tmp/restore-test
borg extract --list ::system-2026-09-03T02:30:00 etc/ssh/sshd_config
Comprueba además la integridad del repositorio. La segunda línea de cada bloque vuelve a leer los datos y recalcula las sumas de verificación, en restic solo sobre una parte para que la ejecución no dure horas:
restic check
restic check --read-data-subset=1/7
borg check
borg check --verify-data
Comprobación: restic check termina con no errors were found, y borg check sin ningún mensaje de error. Un repositorio que solo se comprueba una vez al año puede llevar once meses estropeado.
La prueba grande, una vez al año
La prueba pequeña demuestra que los archivos se pueden leer. No demuestra que vayas a conseguir que el servicio vuelva a funcionar. Para eso hace falta la pasada completa en un segundo servidor vacío: instalar el sistema base, aplicar la lista de paquetes, conectar el repositorio, recuperar los datos, importar el dump y arrancar los servicios. Cronometra el tiempo. Esa cifra es tu duración real de restauración y, por experiencia, es varias veces la estimada.
Apunta lo que ha faltado. Casi siempre son las mismas cosas: un archivo fuera de las rutas respaldadas, un servicio con su configuración en /opt, un certificado sin la clave de la cuenta, una base de datos sin usuarios ni permisos. Esa lista es el fruto de la prueba.
Errores frecuentes y soluciones
Host key verification failed. El servicio se ejecuta como root, y root nunca ha confirmado la clave del host del destino. Ejecuta una vez a mano ssh destino-backup true o ssh-keyscan -H 203.0.113.50 >> /root/.ssh/known_hosts. Si en la consola funciona y en el timer no, casi siempre es este el fallo.
Permission denied (publickey). Usuario equivocado, clave equivocada o permisos equivocados en el destino: .ssh necesita 700, authorized_keys 600, y los dos pertenecen al usuario del destino.
Is there a repository at the following location? restic no encuentra ninguna estructura de repositorio: ruta equivocada, restic init que no se ha ejecutado nunca, o un destino que en ese momento no está accesible.
Fatal: wrong password or no key found El archivo de contraseña no encaja con el repositorio, casi siempre porque se ha vuelto a generar después. Comprueba con cat -A /etc/restic/repo.pass si se ha colado algún espacio.
repository is already locked exclusively by Una ejecución interrumpida ha dejado su bloqueo. Comprueba primero que ya no hay nada en marcha y usa después restic unlock. En Borg el mensaje es Failed to create/acquire the lock con el añadido (timeout), y el comando es borg break-lock. Los dos son arriesgados mientras siga activa una ejecución.
Warning: The repository at location ... was previously located at ... La dirección del repositorio ha cambiado y Borg pregunta de forma interactiva. Dentro de una unit, el comando se queda esperando una respuesta que no llega nunca. Cuando hayas comprobado que se trata del mismo repositorio, pon BORG_RELOCATED_REPO_ACCESS_IS_OK=yes en el archivo de entorno.
No space left on device en el destino. O la limpieza no se ejecuta en absoluto, o se ejecuta sin --prune o sin borg compact. Si al revés ha sido un dump el que ha llenado el sistema de archivos raíz, te ayuda Disco lleno: encontrar y liberar espacio en un servidor Linux.
La ejecución informa de éxito, pero apenas respalda nada. Alguna exclusión va demasiado lejos, o hay una ruta mal escrita. Compara restic stats latest con el valor del día anterior. Un backup que de repente es órdenes de magnitud más pequeño es una alarma y no un éxito.
Diferencias entre las distribuciones
- Los nombres de los paquetes son iguales en los cuatro sistemas:
resticyborgbackup. Las versiones que entrega cada uno, no. - Logs: Debian 13 y muchas instalaciones de Debian 12 no traen rsyslog. Allí la salida de la ejecución la encuentras únicamente en el journal, es decir, con
journalctl -u backup.service. En Ubuntu 22.04 y 24.04 existe además el almacenamiento en/var/log. - Montar estados del backup:
restic mountyborg mountnecesitanfuse3. Si falta el paquete, el comando aborta con un aviso sobre unfusermount3que no existe. El camino sin FUSE esrestic restoreoborg extract. - Herramienta de base de datos: Debian entrega únicamente MariaDB, y allí se llama
mariadb-dump, conmysqldumpcomo enlace hacia ella. En Ubuntu también puede correr MySQL 8, y allí solo existemysqldump.
La comprobación final
La estrategia está terminada cuando puedes demostrar estos siete puntos con un comando y no con una suposición:
restic snapshotsoborg listmuestra un estado de esta noche.systemctl list-timers backup.timerindica una próxima hora de arranque.restic checkoborg checkno informa de ningún error.- Este mes has recuperado un archivo suelto y después era idéntico al original.
- El escalonado se corresponde con la retención planificada y el repositorio no crece sin límite.
- La contraseña está en un segundo sitio y ya la has usado desde ahí alguna vez.
- Al menos un almacenamiento acepta backups sin que el servidor pueda borrarlos.
Si falta el punto cuatro, lo que tienes es una suposición. Si falta el seis, basura cifrada. Y si falta el siete, un backup que no sobrevive justo al ataque para el que más falta hace.
Preguntas frecuentes
¿Qué significa la regla 3-2-1 en un solo servidor root?
¿Un RAID o una imagen del sistema ya son un backup?
restic o Borg: ¿cuál encaja en cada caso?
¿Por qué mi repositorio no se hace más pequeño aunque borre estados antiguos?
¿Puedo copiar sin más una base de datos en marcha como si fuera un archivo?
¿Qué pasa si pierdo la contraseña del repositorio?
¿Con qué frecuencia debería probar la restauración?
¿Por qué mi backup funciona a mano pero no en el timer de systemd?
2026 KernelHost GmbH. Todos los derechos reservados. Esta guía está protegida por derechos de autor. Su publicación en otros sitios web, aunque sea de forma parcial o modificada, no está permitida sin nuestro consentimiento por escrito. Las citas con indicación de la fuente y un enlace son muy bienvenidas.

