Restic es un programa de copias de seguridad escrito en Go que cifra, deduplica y comprime los datos antes de enviarlos a un repositorio, que puede estar en un disco local, en otro servidor por SFTP o en almacenamiento de objetos compatible con S3. Todo se hace desde el cliente: el destino solo guarda bloques cifrados. En este tutorial instalarás Restic en Ubuntu 24.04, crearás un repositorio en un bucket S3 compatible (con la alternativa SFTP), automatizarás las copias con un timer de systemd, aplicarás una política de retención y restaurarás archivos.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo.
  • Un destino para las copias, fuera del servidor:
    • Un bucket en un servicio de almacenamiento compatible con S3, con su endpoint, una clave de acceso (access key) y una clave secreta, o
    • Otro servidor al que puedas conectarte por SSH/SFTP con una clave.

Paso 1: Instalar Restic

Restic está en los repositorios de Ubuntu:

sudo apt update
sudo apt install restic

Comprueba la versión:

restic version
restic 0.16.4 compiled with go1.22.2 on linux/amd64

Esta versión usa por defecto el formato de repositorio 2, con compresión. Si necesitas una versión más reciente, el proyecto publica binarios en su página de GitHub, pero la del repositorio de Ubuntu es suficiente para todo lo que se ve en esta guía.

Paso 2: Guardar la configuración y la contraseña

Restic lee la ubicación del repositorio, la contraseña y las credenciales de variables de entorno. Guardarlas en archivos que solo root puede leer permite usarlas igual en la terminal y en systemd.

Crea el directorio de configuración:

sudo install -d -m 700 /etc/restic

Genera una contraseña aleatoria para el repositorio:

sudo sh -c 'openssl rand -base64 32 > /etc/restic/password'
sudo chmod 600 /etc/restic/password

Crea el archivo de entorno:

sudo nano /etc/restic/env

Para un bucket S3 compatible, usa este contenido. Sustituye s3.example.com por el endpoint de tu proveedor, your_bucket por el nombre del bucket y añade tus claves:

RESTIC_REPOSITORY=s3:https://s3.example.com/your_bucket/web01
RESTIC_PASSWORD_FILE=/etc/restic/password
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key

El sufijo /web01 crea el repositorio en un prefijo dentro del bucket, así puedes usar el mismo bucket para varios servidores con un repositorio cada uno.

Si prefieres un servidor remoto por SFTP, el archivo solo necesita el repositorio y la contraseña. Restic usa el cliente ssh del sistema, así que la clave y el usuario se configuran como en cualquier conexión SSH de root:

RESTIC_REPOSITORY=sftp:backup@backup_server_ip:/srv/restic/web01
RESTIC_PASSWORD_FILE=/etc/restic/password

Protege el archivo:

sudo chmod 600 /etc/restic/env

Paso 3: Inicializar el repositorio

Las copias se ejecutan como root para poder leer todo el sistema. Abre una shell de root y carga las variables. set -a exporta automáticamente todas las variables que se definen al leer el archivo:

sudo -i
set -a; . /etc/restic/env; set +a

Inicializa el repositorio:

restic init
created restic repository 7b1c2e9f04 at s3:https://s3.example.com/your_bucket/web01

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.

Si usas SFTP y es la primera conexión, ejecuta antes ssh backup@backup_server_ip como root para aceptar la huella del servidor. Restic no puede responder a esa pregunta por ti.

Paso 4: Hacer la primera copia

Crea un archivo con patrones de exclusión para no copiar cachés ni temporales:

nano /etc/restic/excludes
/home/*/.cache
/root/.cache
/var/tmp
*.tmp
node_modules

Lanza la copia de los directorios importantes:

restic backup /etc /home /root /var/www \
    --exclude-file /etc/restic/excludes \
    --exclude-caches \
    --tag diaria
  • --exclude-file aplica los patrones del archivo anterior.
  • --exclude-caches omite los directorios que contienen un archivo CACHEDIR.TAG.
  • --tag etiqueta la instantánea, útil para filtrar después.

Al terminar, Restic muestra un resumen:

Files:       18342 new,     0 changed,     0 unmodified
Dirs:         2210 new,     0 changed,     0 unmodified
Added to the repository: 812.411 MiB (790.022 MiB stored)

processed 18342 files, 1.921 GiB in 1:42
snapshot 3f2a9c1b saved

Ejecuta la misma copia otra vez. Esta vez casi todos los archivos aparecerán como unmodified y Added to the repository será de unos pocos kilobytes: Restic solo envía los bloques nuevos.

Lista las instantáneas:

restic snapshots
ID        Time                 Host        Tags        Paths
----------------------------------------------------------------
3f2a9c1b  2026-09-25 10:31:02  web01       diaria      /etc
                                                       /home
                                                       /root
                                                       /var/www
8d0e4a77  2026-09-25 10:36:40  web01       diaria      /etc
...
----------------------------------------------------------------
2 snapshots

Paso 5: Aplicar una política de retención

Sin retención, el repositorio crece indefinidamente. restic forget decide qué instantáneas conservar y --prune borra los datos que ya no usa ninguna:

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

Con esta política se conservan las últimas 7 copias diarias, 4 semanales y 12 mensuales. Restic agrupa las instantáneas por host y rutas, así que la retención se aplica por separado a cada servidor y conjunto de directorios.

Si quieres ver qué borraría sin hacerlo, añade --dry-run.

Paso 6: Automatizar con systemd

Sal de la shell de root con exit. Crea un script que haga la copia y aplique la retención:

sudo nano /usr/local/sbin/restic-backup.sh
#!/usr/bin/env bash
set -euo pipefail

restic backup /etc /home /root /var/www \
    --exclude-file /etc/restic/excludes \
    --exclude-caches \
    --tag diaria

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

El script no carga las variables: las proporcionará systemd desde /etc/restic/env. Con set -e, si la copia falla no se ejecuta la retención y el servicio queda marcado como fallido.

Hazlo ejecutable:

sudo chmod 700 /usr/local/sbin/restic-backup.sh

Crea la unidad de servicio:

sudo nano /etc/systemd/system/restic-backup.service
[Unit]
Description=Copia de seguridad con Restic
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/restic/env
Environment=RESTIC_CACHE_DIR=/var/cache/restic
ExecStart=/usr/local/sbin/restic-backup.sh
Nice=10
IOSchedulingClass=idle

RESTIC_CACHE_DIR fija la caché local de metadatos, que acelera mucho las copias siguientes.

Crea el timer para ejecutarla cada noche a las 02:00:

sudo nano /etc/systemd/system/restic-backup.timer
[Unit]
Description=Copia diaria con Restic

[Timer]
OnCalendar=*-*-* 02:00:00
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target

Activa el timer y prueba el servicio una vez a mano:

sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
sudo systemctl start restic-backup.service

Comprueba el resultado:

systemctl status restic-backup.service --no-pager
sudo journalctl -u restic-backup.service -n 20 --no-pager

El estado debe ser inactive (dead) con status=0/SUCCESS en la línea del proceso, y el registro debe terminar con snapshot ... saved seguido de la salida de forget. Revisa la próxima ejecución:

systemctl list-timers restic-backup.timer

Paso 7: Restaurar archivos

Abre una shell de root y carga las variables como en el paso 3:

sudo -i
set -a; . /etc/restic/env; set +a

Explora el contenido de la última instantánea:

restic ls latest /etc/nginx

Si no sabes en qué instantánea está un archivo, búscalo:

restic find nginx.conf

Restaura en un directorio temporal solo lo que necesitas. latest se refiere a la instantánea más reciente; también puedes usar un ID de restic snapshots:

restic restore latest --target /tmp/restore --include /etc/nginx
restoring <Snapshot 8d0e4a77 of [/etc /home /root /var/www] at 2026-09-25 10:36:40 by root@web01> to /tmp/restore

Restic recrea la ruta completa bajo el destino. Compara y copia a su sitio:

diff -r /tmp/restore/etc/nginx /etc/nginx
cp -a /tmp/restore/etc/nginx/. /etc/nginx/

Para restaurar en un servidor nuevo, instala Restic, crea /etc/restic/env y /etc/restic/password con los mismos valores y ejecuta restic restore de la misma forma.

Paso 8: Verificar el repositorio

restic check comprueba la estructura del repositorio. Con --read-data-subset además descarga y verifica una parte de los datos, lo que detecta bloques corruptos sin descargar todo el repositorio cada vez:

restic check --read-data-subset=5%
...
read 5.0% of data packs
no errors were found

Ejecútalo con regularidad, por ejemplo una vez a la semana, y haz de vez en cuando una restauración completa de prueba.

Solución de problemas

repository is already locked. Hay otra operación en curso, o una anterior se interrumpió y dejó un bloqueo. Si estás seguro de que no hay ningún restic en marcha contra ese repositorio, ejecuta restic unlock.

wrong password or no key found. RESTIC_PASSWORD_FILE apunta a un archivo con una contraseña distinta de la usada en restic init. Recupera la original desde tu gestor de contraseñas.

Fatal: unable to open config file: Stat: ... Access Denied. Las claves S3 no tienen permisos sobre el bucket, o el endpoint o el nombre del bucket son incorrectos. Revisa /etc/restic/env.

El servicio funciona a mano pero falla desde el timer. Normalmente falta una variable. Recuerda que en /etc/restic/env no se usa export ni comillas innecesarias, porque systemd lo lee como CLAVE=valor.

Conclusión

Tienes copias diarias de tu servidor cifradas y deduplicadas en un almacenamiento externo, con retención automática, verificación del repositorio y un procedimiento de restauración probado. Como siguientes pasos, programa restic check en un segundo timer semanal, avisa cuando el servicio falle con OnFailure= en la unidad, y guarda una segunda copia del repositorio en otro proveedor con restic copy para cumplir la regla 3-2-1.