Restic: backups cifrados con deduplicación para tu servidor Linux
Etiquetas: restic,backups,linux,seguridad,automatización,devopsYa tenía backups con rsync y cron, pero rsync copia archivos, no snapshots. Si borras accidentalmente un fichero y el backup se sincroniza antes de que te des cuenta, lo pierdes. Restic resuelve eso y añade algo que rsync nunca dará: cifrado, deduplicación y snapshots con historial navegable.
Qué hace Restic diferente
| Característica | rsync | Restic |
|---|---|---|
| Cifrado AES-256 | No | Sí |
| Deduplicación | No | Sí (a nivel de bloque) |
| Snapshots navegables | No | Sí |
| Múltiples backends | No | SFTP, S3, Backblaze, rclone… |
| Comprobación de integridad | No | restic check |
| Política de retención | Manual | restic forget --prune |
La deduplicación es especialmente útil en backups de bases de datos y directorios de configuración que cambian poco: un repositorio de Restic que lleva 6 meses de backups diarios suele ocupar mucho menos que 180 copias completas.
Instalación
En Ubuntu/Debian, la versión del repositorio oficial suele ir retrasada. Mejor descargar el binario directamente desde las releases oficiales de GitHub:
# Descarga la última versión (ajusta la versión si hay una más reciente)
wget https://github.com/restic/restic/releases/download/v0.17.3/restic_0.17.3_linux_amd64.bz2
bunzip2 restic_0.17.3_linux_amd64.bz2
chmod +x restic_0.17.3_linux_amd64
sudo mv restic_0.17.3_linux_amd64 /usr/local/bin/restic
# Verificar
restic version
O con los repositorios del sistema si no te importa la versión:
sudo apt install restic # Debian/Ubuntu
sudo dnf install restic # Fedora/RHEL
Conceptos clave antes de empezar
- Repositorio: el destino donde Restic guarda los backups. Puede ser una carpeta local, un servidor SFTP, un bucket S3, etc.
- Snapshot: cada vez que ejecutas
restic backup, Restic guarda un snapshot puntual. Los snapshots comparten bloques deduplicados, por lo que no multiplican el espacio. - Password: el repositorio se cifra con una contraseña. Sin ella, los datos son ilegibles. Guárdala en un gestor de contraseñas o en un fichero separado del backup.
Inicializar un repositorio
Opción A: repositorio local
restic init --repo /opt/backups/mi-servidor
Opción B: repositorio en servidor remoto via SFTP
restic init --repo sftp:usuario@servidor-backup:/opt/restic/mi-servidor
Opción C: repositorio en S3 (o compatible: Backblaze B2, MinIO…)
export AWS_ACCESS_KEY_ID="TU_ACCESS_KEY_AQUI"
export AWS_SECRET_ACCESS_KEY="TU_SECRET_KEY_AQUI"
restic init --repo s3:s3.eu-west-1.amazonaws.com/mi-bucket-backups/mi-servidor
En los tres casos, Restic te pedirá una contraseña para cifrar el repositorio. Guárdala bien — sin ella no puedes restaurar nada.
Fichero de variables de entorno
Para no escribir la contraseña en cada comando, crea un fichero de variables:
# /etc/restic/env.sh (solo root puede leerlo)
sudo mkdir -p /etc/restic
sudo chmod 700 /etc/restic
sudo tee /etc/restic/env.sh > /dev/null <<'EOF'
export RESTIC_REPOSITORY="/opt/backups/mi-servidor"
export RESTIC_PASSWORD="TU_CONTRASENA_AQUI"
EOF
sudo chmod 600 /etc/restic/env.sh
A partir de ahora, antes de cualquier comando de Restic:
source /etc/restic/env.sh
O con variables de entorno en línea para scripts:
env $(cat /etc/restic/env.sh | grep export | sed 's/export //') restic snapshots
Primer backup
source /etc/restic/env.sh
# Backup de los datos de Docker y configuraciones
restic backup \
/opt/app/ \
/etc/nginx/ \
/home/usuario/ \
--exclude='/opt/app/logs' \
--exclude='*.tmp' \
--tag servidor-web
La salida muestra cuántos ficheros procesó, cuántos son nuevos y el espacio ahorrado por deduplicación:
Files: 1234 new, 567 changed, 8901 unmodified
Dirs: 45 new, 12 changed, 89 unmodified
Added to the repo: 234.567 MiB
processed 10702 files, 1.234 GiB in 0:23
snapshot a1b2c3d4 saved
Ver y navegar snapshots
# Listar todos los snapshots
restic snapshots
# Listar ficheros dentro de un snapshot específico
restic ls a1b2c3d4
# Buscar un fichero en todos los snapshots
restic find --tag servidor-web nombre-fichero.conf
Salida de restic snapshots:
ID Time Host Tags Paths
────────────────────────────────────────────────────────────────────
a1b2c3d4 2026-05-11 03:00:02 mi-servidor servidor-web /opt/app, /etc/nginx, /home/usuario
e5f6a7b8 2026-05-10 03:00:01 mi-servidor servidor-web /opt/app, /etc/nginx, /home/usuario
Restaurar datos
Restauración completa de un snapshot
# Restaura todo en /tmp/restauracion para revisar antes de mover
restic restore a1b2c3d4 --target /tmp/restauracion
Restaurar solo un fichero o directorio
# Restaura solo nginx.conf del snapshot más reciente
restic restore latest --target /tmp/restauracion \
--include /etc/nginx/nginx.conf
Montar el repositorio como sistema de ficheros (útil para explorar)
# Requiere FUSE instalado: sudo apt install fuse
mkdir -p /mnt/restic-backups
restic mount /mnt/restic-backups &
# Ahora puedes navegar por todos los snapshots
ls /mnt/restic-backups/snapshots/
# → a1b2c3d4/ e5f6a7b8/ latest/
# Cuando acabes
fusermount -u /mnt/restic-backups
Política de retención automática
Sin política de retención, el repositorio crece indefinidamente. Esta es la configuración que uso para backups diarios:
# 7 días diarios, 4 semanas, 6 meses, 1 año
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--keep-yearly 1 \
--tag servidor-web \
--prune
--prune elimina físicamente los datos no referenciados. Sin él, forget solo elimina los metadatos del snapshot pero no libera espacio.
Verificar la integridad del repositorio
# Verificación rápida de metadatos
restic check
# Verificación completa leyendo todos los datos (lento, hazlo mensualmente)
restic check --read-data
Si restic check falla, el repositorio tiene corrupción. Por eso siempre se recomienda tener al menos dos repositorios en destinos distintos (la conocida regla 3-2-1).
Automatizar con systemd timer
Restic se integra perfectamente con systemd timers, que permiten capturar la salida en journald y ejecutar la tarea aunque el servidor estuviera apagado a la hora programada.
/etc/systemd/system/restic-backup.service:
[Unit]
Description=Backup diario con Restic
After=network.target
[Service]
Type=oneshot
User=root
EnvironmentFile=/etc/restic/env.sh
ExecStart=/usr/local/bin/restic backup \
/opt/app/ \
/etc/nginx/ \
/home/usuario/ \
--exclude='/opt/app/logs' \
--tag servidor-web
ExecStartPost=/usr/local/bin/restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--tag servidor-web \
--prune
StandardOutput=journal
StandardError=journal
/etc/systemd/system/restic-backup.timer:
[Unit]
Description=Ejecuta backup Restic diariamente
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=10min
[Install]
WantedBy=timers.target
Activar:
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
# Verificar que está activo
sudo systemctl list-timers restic-backup.timer
RandomizedDelaySec=10min distribuye los backups en ventanas aleatorias para evitar que todos los servidores golpeen el destino SFTP o S3 al mismo tiempo.
Notificaciones por email al terminar
Combinando con el sistema de notificaciones por email con msmtp, podemos recibir un resumen del backup. Modifica ExecStart por un script wrapper:
/usr/local/bin/restic-backup.sh:
#!/bin/bash
set -euo pipefail
source /etc/restic/env.sh
LOG=$(mktemp)
STATUS=0
restic backup \
/opt/app/ \
/etc/nginx/ \
/home/usuario/ \
--exclude='/opt/app/logs' \
--tag servidor-web > "$LOG" 2>&1 || STATUS=$?
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--tag servidor-web \
--prune >> "$LOG" 2>&1 || STATUS=$?
SUBJECT="[Backup] $(hostname) - $(date '+%Y-%m-%d')"
[ $STATUS -ne 0 ] && SUBJECT="[ERROR Backup] $(hostname) - $(date '+%Y-%m-%d')"
cat "$LOG" | mail -s "$SUBJECT" usuario@ejemplo.com
rm -f "$LOG"
exit $STATUS
chmod +x /usr/local/bin/restic-backup.sh
Y en el .service, cambia ExecStart y ExecStartPost por una sola línea:
ExecStart=/usr/local/bin/restic-backup.sh
Comprobación semanal de integridad
Añade un segundo timer para la verificación semanal, que es más costosa:
/etc/systemd/system/restic-check.service:
[Unit]
Description=Verificación semanal de integridad Restic
After=network.target
[Service]
Type=oneshot
User=root
EnvironmentFile=/etc/restic/env.sh
ExecStart=/usr/local/bin/restic check
StandardOutput=journal
StandardError=journal
/etc/systemd/system/restic-check.timer:
[Unit]
Description=Verifica integridad del repositorio Restic cada semana
[Timer]
OnCalendar=Sun *-*-* 04:00:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl enable --now restic-check.timer
Ver el estado en el log del sistema
# Último backup
journalctl -u restic-backup.service -n 50
# Seguir en tiempo real durante la ejecución manual
journalctl -u restic-backup.service -f
# Historial de ejecuciones del timer
systemctl status restic-backup.timer
Conclusión
Restic no reemplaza completamente a rsync para casos de sincronización de directorios en vivo, pero para backups con historial, es claramente superior: cifrado de serie, deduplicación transparente, y snapshots navegables sin scripts adicionales. La integración con systemd timers y el envío de notificaciones por email cierra el ciclo: sabes que el backup se ejecutó, cuándo falló, y puedes restaurar cualquier punto en el tiempo en minutos.
La clave real de cualquier estrategia de backups no es el software que elijas, sino verificar que puedes restaurar. Prueba restic restore en un directorio temporal antes de que lo necesites de verdad.