Por qué automatizar sus copias de seguridad con Restic
Un VPS aloja a menudo datos irreemplazables: bases de datos, volúmenes Docker, ficheros de configuración. Restic responde a tres exigencias clave de una buena estrategia: el cifrado (AES-256, el repositorio es inutilizable sin la contraseña), la deduplicación (los bloques idénticos solo se almacenan una vez, lo que reduce drásticamente el volumen y el costo) y el soporte de backends variados (S3, Backblaze B2, SFTP, almacenamiento local). Autoalojar Restic en el VPS en lugar de depender de un servicio de backup gestionado le da el control total del cifrado: la clave permanece en su poder y el proveedor de almacenamiento solo ve blobs opacos. Es la base de una estrategia 3-2-1 seria.
Lo que Restic le aporta
- Cifrado AES-256 del lado del cliente: el backend de almacenamiento solo ve datos ilegibles.
- Deduplicación por bloques que reduce mucho el tamaño y el costo de las copias sucesivas.
- Snapshots incrementales rápidos: solo se transfieren los bloques nuevos en cada ejecución.
- Múltiples backends (S3, Backblaze B2, SFTP, rest-server, local) sin cambiar de flujo de trabajo.
- Restauración granular: un fichero, una carpeta o un snapshot completo mediante
restic restore. - Política de retención automatizada con
forget --prune(conservar N diarios, M semanales...).
La regla 3-2-1: por qué un snapshot del proveedor no basta
Activar los snapshots de su proveedor de VPS es útil, pero no es una estrategia de copias de seguridad: es una única copia adicional, en el mismo proveedor, que comparte la suerte de su VM. Tres escenarios lo demuestran. Si la VM se elimina (un error de manipulación, un impago, una rescisión), sus snapshots suelen desaparecer con ella. Si un atacante toma el control de su cuenta en el proveedor, borra VM y snapshots en unos clics o mediante la API. Y un snapshot nunca se restaura a modo de prueba: una base de datos congelada en plena escritura puede resultar inservible el día en que la necesite.
La regla 3-2-1 responde a estos tres riesgos: tres copias de los datos, en dos soportes distintos, una de ellas fuera del proveedor y cifrada antes de salir del servidor. Restic construye precisamente ese último eslabón, el único que sobrevive a la pérdida completa de la cuenta del proveedor.
Las tres copias de una estrategia 3-2-1 en un VPS
- Copia 1, los datos vivos en el disco del VPS: es el original y la fuente de las restauraciones más rápidas.
- Copia 2, los snapshots del proveedor: cubren una actualización fallida o un error de configuración, devolviendo toda la máquina a un estado anterior.
- Copia 3, el repositorio Restic en otro proveedor de almacenamiento de objetos: cifrado del lado del cliente, queda fuera del alcance del panel de su proveedor.
- Dos soportes realmente separados: el disco del VPS por un lado, el almacenamiento de objetos de un tercero por otro, con credenciales distintas.
Requisitos previos para este despliegue
Restic es frugal: funciona en cualquier VPS, incluso con 1 vCPU y 1 GB de RAM, ya que la deduplicación consume un poco de memoria en proporción al tamaño del repositorio. Necesita el binario restic, un backend de destino remoto (un bucket compatible con S3 en un proveedor, u otro servidor por SFTP) y sus credenciales. Aquí no hace falta Docker: Restic es una herramienta de línea de comandos.
Compruebe la versión que ofrece su distribución: Debian 13 y Ubuntu 26.04 incluyen la 0.18, pero Ubuntu 24.04 va por la 0.16.4 y Debian 12 por la 0.14.0, demasiado antigua para la opción --stdin-from-command que se usa más abajo (aparecida en la 0.17.0). En ese caso, instale el binario oficial desde la página de releases (0.19.1, publicada el 5 de julio de 2026): solo estos binarios oficiales incluyen el comando restic self-update, mientras que un paquete de distribución se actualiza con apt. Prevea por último un timer de systemd (o cron) para la automatización y un lugar seguro fuera del VPS para guardar la contraseña del repositorio.
Backblaze B2 o Cloudflare R2: elegir el backend S3
Desplace la tabla
| Criterio | Backblaze B2 | Cloudflare R2 |
|---|---|---|
| Almacenamiento gratuito | Los primeros 10 GB | 10 GB-mes al mes (clase Standard) |
| Salida de datos (egress) | Gratuita hasta 3 veces el volumen almacenado de media en el mes, y sin límite hacia las CDN asociadas (Cloudflare, Fastly) | Gratuita, sin tope |
| Endpoint S3 | Propio de la región de la cuenta, por ejemplo `s3.us-west-004.backblazeb2.com` | `<account-id>.r2.cloudflarestorage.com`, región `auto` |
| Claves de acceso | Una Application Key dedicada: la API S3 rechaza la clave maestra | Un token de API de R2 con permisos de lectura y escritura sobre los objetos |
| Punto de atención | Una restauración completa y frecuente puede superar la cuota de salida gratuita | Las pruebas de restauración periódicas no añaden coste de salida |
Configurar copias de seguridad Restic automatizadas
Instalar Restic y preparar el archivo de entorno
Instale
restic(paquete reciente o binario oficial, vea los requisitos) y cree después/root/.restic-env. Escríbalo en líneas simplesCLAVE=valor, sinexport: es el formato que lee la directivaEnvironmentFile=de systemd, y también se carga en un shell. Con Restic, B2 se usa preferentemente a través de su API compatible con S3:# /root/.restic-env (Backblaze B2, S3 API) RESTIC_REPOSITORY=s3:https://s3.us-west-004.backblazeb2.com/my-bucket RESTIC_PASSWORD=change-me AWS_ACCESS_KEY_ID=b2-key-id AWS_SECRET_ACCESS_KEY=b2-application-key # Cloudflare R2 # RESTIC_REPOSITORY=s3:https://<account-id>.r2.cloudflarestorage.com/my-bucketRestrinja los permisos del archivo y cárguelo en su sesión:
chmod 600 /root/.restic-env set -a; . /root/.restic-env; set +aInicializar el repositorio cifrado
restic initEste comando crea la estructura del repositorio y sella el cifrado con su contraseña; los repositorios recientes (formato 2, desde Restic 0.14.0) también comprimen los datos. Guarde esa contraseña fuera del VPS, en un gestor de contraseñas o en una bóveda en otra máquina: sin ella no es posible ninguna restauración, aunque disponga del bucket completo.
Lanzar una primera copia de seguridad
Respalde sus directorios críticos y después sus bases de datos. Para un volcado, prefiera
--stdin-from-commanda una tuberíapg_dump | restic backup --stdin: Restic no puede saber si un flujo leído por la entrada estándar está completo, y un volcado que falle a mitad produciría un snapshot truncado sin ningún error. Con--stdin-from-command, un código de salida distinto de cero del comando cancela la copia y no se crea ningún snapshot.restic backup /etc /var/www /opt/docker-data restic backup --stdin-filename mydb.sql --stdin-from-command -- pg_dump -U postgres mydb restic snapshotsDefinir una política de retención
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --pruneSiete diarias cubren una semana entera, lo suficiente para detectar una corrupción que solo se manifiesta al cabo de unos días. Cuatro semanales abren una ventana de un mes para un problema de aplicación lento, como datos que desaparecen poco a poco. Seis mensuales permiten volver a un estado anterior a una migración fallida. La pasada
--prunees imprescindible:forgetpor sí solo retira los snapshots de la lista sin liberar espacio, y la factura de almacenamiento sigue creciendo.Verificar la integridad: check y después read-data
Estos comandos no comprueban lo mismo:
restic check restic check --read-data-subset=10% restic check --read-datarestic checkvalida la estructura del repositorio (snapshots, árboles, índices, packs) sin leer el contenido de los archivos de datos: es rápido y se lanza tras cadaforget --prune.--read-datadescarga y verifica todos los packs, lo que lleva tiempo y consume ancho de banda de salida. Entre ambos,--read-data-subsetcomprueba una parte aleatoria (10%, o un tamaño como5G) o un tramo fijo (de1/5a5/5, para cubrirlo todo en cinco pasadas). Una verificación parcial cada semana y una completa una vez al mes es un buen compromiso.Escribir el script de copia y su servicio systemd
Agrupe los pasos en un script. Primero escribe un archivo centinela con marca de tiempo, que servirá para la prueba de restauración, y se detiene en el primer error gracias a
set -eu:#!/bin/sh # /usr/local/bin/restic-backup.sh set -eu date +%s > /opt/restic-sentinel.txt restic backup /etc /var/www /opt/docker-data /opt/restic-sentinel.txt restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune restic checkEl servicio lo ejecuta con las variables del archivo de entorno, sin que ningún secreto aparezca en la definición de la unidad:
# /etc/systemd/system/restic-backup.service [Unit] Description=Restic backup After=network-online.target Wants=network-online.target [Service] Type=oneshot EnvironmentFile=/root/.restic-env ExecStart=/usr/local/bin/restic-backup.shPlanificar con un timer de systemd
El timer lanza el servicio cada noche.
Persistent=truerecupera una ejecución perdida si el VPS estaba apagado a la hora prevista, yRandomizedDelaySec=900reparte el arranque en quince minutos, algo útil cuando varios servidores apuntan al mismo bucket:# /etc/systemd/system/restic-backup.timer [Unit] Description=Daily restic backup [Timer] OnCalendar=*-*-* 03:00:00 Persistent=true RandomizedDelaySec=900 [Install] WantedBy=timers.targetActívelo y compruebe después la próxima ejecución y los registros de la última:
chmod 700 /usr/local/bin/restic-backup.sh systemctl daemon-reload systemctl enable --now restic-backup.timer systemctl list-timers restic-backup.timer journalctl -u restic-backup.service --since todaySi prefiere
cron, una línea0 3 * * *que cargue el archivo de entorno y llame al mismo script cumple la función, sin la recuperación que ofrecePersistent=.Automatizar la prueba de restauración
Una copia que nunca se ha restaurado sigue siendo una hipótesis. Este segundo script restaura únicamente el archivo centinela del último snapshot y lo compara con el original: si la copia de la noche falló o si el repositorio ya no devuelve nada,
cmpfalla y el servicio pasa al estadofailed. La prueba apunta al snapshot más reciente: si añade volcados--stdin-from-commandal script de copia, colóquelos antes de la copia de los archivos, que debe seguir siendo la última.#!/bin/sh # /usr/local/bin/restic-restore-test.sh set -eu rm -rf /tmp/restic-test-restore restic restore latest --target /tmp/restic-test-restore --include /opt/restic-sentinel.txt cmp /tmp/restic-test-restore/opt/restic-sentinel.txt /opt/restic-sentinel.txtPlanifíquelo cada semana, después de la copia nocturna:
# /etc/systemd/system/restic-restore-test.service [Service] Type=oneshot EnvironmentFile=/root/.restic-env ExecStart=/usr/local/bin/restic-restore-test.sh # /etc/systemd/system/restic-restore-test.timer [Timer] OnCalendar=Sun 05:00:00 Persistent=true [Install] WantedBy=timers.targetActive el timer con
systemctl enable --now restic-restore-test.timery conecte el estadofailedde ambos servicios a su supervisión. Una vez por trimestre, restaure además un directorio real, base de datos incluida, en una máquina de pruebas.
Secretos de Restic: un archivo aislado, nunca escritos en la unidad
No coloque nunca RESTIC_PASSWORD ni las claves S3 en una línea Environment= de una unidad systemd, en un script versionado o en un Dockerfile: las variables declaradas en la unidad pueden leerse con systemctl show. El archivo /root/.restic-env con chmod 600, cargado por EnvironmentFile=, mantiene los secretos fuera de la definición de la unidad. Para ir más lejos, la directiva LoadCredential= de systemd expone un secreto en un directorio reservado al servicio ($CREDENTIALS_DIRECTORY): Restic lee entonces su contraseña mediante RESTIC_PASSWORD_FILE.
Solución de problemas: errores frecuentes
restic init o el primer backup falla sobre el bucket. Compruebe primero que las variables están cargadas (echo $RESTIC_REPOSITORY) y después el endpoint: en B2 debe corresponder a la región de su cuenta, y el endpoint de AWS (s3.amazonaws.com) es un error frecuente. Una Application Key de B2 restringida a un solo bucket también necesita el permiso listAllBucketNames para funcionar con las herramientas S3, y la clave maestra de la cuenta no sirve con la API S3. En R2, el token debe tener permisos de lectura y escritura sobre los objetos del bucket.
El timer no se dispara. Bastan tres comandos: systemctl status restic-backup.timer (activo o no), systemctl list-timers --all | grep restic (próxima ejecución), journalctl -u restic-backup.service --since today (registro de la última ejecución). Para validar una expresión OnCalendar, systemd-analyze calendar '*-*-* 03:00:00' debe mostrar la próxima fecha de disparo.
El repositorio sigue bloqueado. Una copia interrumpida (reinicio, corte de red) puede dejar un bloqueo: restic list locks lo muestra y restic unlock elimina los bloqueos caducados. Asegúrese antes de que no haya ninguna otra operación de Restic en curso.
restic check --read-data demasiado largo. En un repositorio de varias decenas de GB, la lectura completa tarda horas y pesa sobre la cuota de salida. Pase a --read-data-subset=10% o a un tramo 1/4 cada semana, y reserve la lectura completa para un mantenimiento mensual.
Plan de recuperación: ¿cuánto se tarda en restaurarlo todo?
La duración de una restauración completa depende del volumen del repositorio, del ancho de banda entre el VPS y el bucket y de la política de salida del proveedor. En R2 la salida es gratuita: nada obliga a escalonar una restauración. En B2 es gratuita hasta tres veces el volumen almacenado de media en el mes; por encima, una restauración completa de un repositorio grande se factura.
No adivine ese tiempo: mídalo. restic stats da el tamaño del repositorio; restaure después un directorio significativo (restic restore latest --target /tmp/test --include /etc) y cronometre la operación para extrapolar. Dos prácticas acortan la recuperación: respaldar solo lo que importa (ni cachés, ni registros, ni /tmp, ni volúmenes Docker abandonados) y anotar en su procedimiento el orden de puesta en servicio, primero las bases de datos y después las aplicaciones que dependen de ellas.
Proteja sus copias de seguridad frente al ransomware activando el modo «append-only» del lado del backend: despliegue un rest-server remoto con la opción --append-only, o utilice un bucket S3 con una política IAM que prohíba las eliminaciones. Así, aunque su VPS quede comprometido y el atacante obtenga las credenciales, no podrá borrar ni cifrar sus snapshots existentes. Combine esto con una ejecución de restic forget --prune desde una máquina distinta que sí disponga de permisos de eliminación.