Ya 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 el repositorio oficial:
# 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 versionO con los repositorios del sistema si no te importa la versión:
sudo apt install restic # Debian/Ubuntu
sudo dnf install restic # Fedora/RHELConceptos 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-servidorOpción B: repositorio en servidor remoto via SFTP#
restic init --repo sftp:usuario@servidor-backup:/opt/restic/mi-servidorOpció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-servidorEn 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.shA partir de ahora, antes de cualquier comando de Restic:
source /etc/restic/env.shO con variables de entorno en línea para scripts:
env $(cat /etc/restic/env.sh | grep export | sed 's/export //') restic snapshotsPrimer 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-webLa 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 savedVer 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.confSalida 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/usuarioRestaurar datos#
Restauración completa de un snapshot#
# Restaura todo en /tmp/restauracion para revisar antes de mover
restic restore a1b2c3d4 --target /tmp/restauracionRestaurar solo un fichero o directorio#
# Restaura solo nginx.conf del snapshot más reciente
restic restore latest --target /tmp/restauracion \
--include /etc/nginx/nginx.confMontar 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-backupsPolí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-dataSi restic check falla, el repositorio tiene corrupción. Por eso siempre se recomienda tener al menos dos repositorios en destinos distintos (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.targetActivar:
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
# Verificar que está activo
sudo systemctl list-timers restic-backup.timerRandomizedDelaySec=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 $STATUSchmod +x /usr/local/bin/restic-backup.shY en el .service, cambia ExecStart y ExecStartPost por una sola línea:
ExecStart=/usr/local/bin/restic-backup.shComprobació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.targetsudo systemctl enable --now restic-check.timerVer 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.timerConclusió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.