Tutorial

Seguridad y monitorización

Automatizar las copias de seguridad de su VPS con Restic

Una copia de seguridad que no se prueba ni se cifra no vale nada el día de un incidente. Restic combina snapshots incrementales, deduplicación y cifrado de extremo a extremo en un único binario. En su VPS se convierte en la red de seguridad automatizada de sus datos, enviados a un almacenamiento de objetos remoto a bajo costo.

11 min de lectura8 pasos
Contenido· Por qué automatizar sus copias de seguridad con Restic1/10
  1. 01Por qué automatizar sus copias de seguridad con Restic
  2. 02Lo que Restic le aporta
  3. 03La regla 3-2-1: por qué un snapshot del proveedor no basta
  4. 04Las tres copias de una estrategia 3-2-1 en un VPS
  5. 05Requisitos previos para este despliegue
  6. 06Backblaze B2 o Cloudflare R2: elegir el backend S3
  7. 07Configurar copias de seguridad Restic automatizadas
  8. 08Secretos de Restic: un archivo aislado, nunca escritos en la unidad
  9. 09Solución de problemas: errores frecuentes
  10. 10Plan de recuperación: ¿cuánto se tarda en restaurarlo todo?

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

CriterioBackblaze B2Cloudflare R2
Almacenamiento gratuitoLos primeros 10 GB10 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 S3Propio 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 accesoUna Application Key dedicada: la API S3 rechaza la clave maestraUn token de API de R2 con permisos de lectura y escritura sobre los objetos
Punto de atenciónUna restauración completa y frecuente puede superar la cuota de salida gratuitaLas pruebas de restauración periódicas no añaden coste de salida

Configurar copias de seguridad Restic automatizadas

  1. 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 simples CLAVE=valor, sin export: es el formato que lee la directiva EnvironmentFile= 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-bucket

    Restrinja los permisos del archivo y cárguelo en su sesión:

    chmod 600 /root/.restic-env
    set -a; . /root/.restic-env; set +a
  2. Inicializar el repositorio cifrado

    restic init

    Este 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.

  3. Lanzar una primera copia de seguridad

    Respalde sus directorios críticos y después sus bases de datos. Para un volcado, prefiera --stdin-from-command a una tubería pg_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 snapshots
  4. Definir una política de retención

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

    Siete 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 --prune es imprescindible: forget por sí solo retira los snapshots de la lista sin liberar espacio, y la factura de almacenamiento sigue creciendo.

  5. 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-data

    restic check valida la estructura del repositorio (snapshots, árboles, índices, packs) sin leer el contenido de los archivos de datos: es rápido y se lanza tras cada forget --prune. --read-data descarga y verifica todos los packs, lo que lleva tiempo y consume ancho de banda de salida. Entre ambos, --read-data-subset comprueba una parte aleatoria (10%, o un tamaño como 5G) o un tramo fijo (de 1/5 a 5/5, para cubrirlo todo en cinco pasadas). Una verificación parcial cada semana y una completa una vez al mes es un buen compromiso.

  6. 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 check

    El 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.sh
  7. Planificar con un timer de systemd

    El timer lanza el servicio cada noche. Persistent=true recupera una ejecución perdida si el VPS estaba apagado a la hora prevista, y RandomizedDelaySec=900 reparte 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.target

    Actí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 today

    Si prefiere cron, una línea 0 3 * * * que cargue el archivo de entorno y llame al mismo script cumple la función, sin la recuperación que ofrece Persistent=.

  8. 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, cmp falla y el servicio pasa al estado failed. La prueba apunta al snapshot más reciente: si añade volcados --stdin-from-command al 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.txt

    Planifí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.target

    Active el timer con systemctl enable --now restic-restore-test.timer y conecte el estado failed de 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.

Proteja sus datos desde el primer día

En un VPS Cloud ServOrbit con plantilla preconfigurada, instala Restic en unos pocos comandos y programa copias de seguridad cifradas hacia el almacenamiento de objetos que elija.