Centro de ayuda

Guías paso a paso sobre servidores, redes y tu cuenta.

Servidor Linux

Copias de seguridad automáticas y cifradas del VPS con restic y rclone (diarias, externas y con restauración probada)

Copias de seguridad automáticas y cifradas del VPS con restic y rclone (diarias, externas y con restauración probada)

La forma más segura de hacer copias de seguridad de un VPS Linux es enviar cada día snapshots cifrados con restic a un almacenamiento fuera del servidor, mantener una política de retención clara y probar la restauración con regularidad. Esta guía lo configura en Debian 12/13, Ubuntu 22.04/24.04 y Rocky Linux / AlmaLinux: instalar restic, elegir un repositorio externo (almacenamiento compatible con S3, SFTP o rclone), volcar las bases de datos, programarlo con un timer de systemd y comprobar que de verdad puedes recuperar tus datos.

Por qué tus copias deben estar fuera del VPS

Una copia en el mismo servidor no es una copia de seguridad: lo que elimine el servidor elimina también la copia. En un VPS cloud de JUSTG, varias acciones normales borran los datos para siempre:

  • Cambio de ubicación (Change location): se instala un VPS nuevo con otra IP y no se copia nada. En cuanto está listo, el VPS antiguo y todos sus datos se eliminan.
  • Renovación vencida: un servicio impagado se suspende en la fecha de vencimiento; si la factura sigue sin pagar 7 días después, el servicio se cancela y sus datos se eliminan.
  • Reinstalar el sistema operativo borra el disco, y una cancelación Immediate elimina el servicio y sus datos en cuanto se procesa.

Súmale un rm -rf mal escrito, una actualización que sale mal o un servidor comprometido, y la regla queda clara: la única copia en la que puedes confiar es la que haces tú y guardas en otro sitio. Antes de cualquier cambio de ubicación, reinstalación o cancelación, lanza una copia a mano y comprueba que existe el snapshot nuevo.

restic cifra los datos en tu VPS antes de subirlos, así que el proveedor de almacenamiento solo ve bloques cifrados. Además deduplica: tras la primera subida completa, cada snapshot diario envía solo lo que ha cambiado.

Paso 1: Instala restic

Debian 12/13, Ubuntu 24.04 y EPEL traen versiones suficientemente recientes:

# Debian 12/13, Ubuntu 24.04
apt update && apt install -y restic
restic version

# Rocky Linux / AlmaLinux 8, 9 (from EPEL)
dnf install -y epel-release && dnf install -y restic

Ubuntu 22.04 trae restic 0.12, que no tiene compresión ni admite el formato de repositorio actual. Ahí, instala el binario oficial y verifica su checksum:

# Official static binary (Ubuntu 22.04 or any distro with an old restic)
VER=0.18.1   # check https://github.com/restic/restic/releases for the latest version
cd /tmp
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/restic_${VER}_linux_amd64.bz2
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS      # must print: OK
bunzip2 restic_${VER}_linux_amd64.bz2
install -m 0755 restic_${VER}_linux_amd64 /usr/local/bin/restic
restic version

Paso 2: Elige un repositorio externo

El repositorio es donde se guardan los snapshots cifrados. Elige una opción y guárdala en /etc/restic/env (líneas simples NAME=value).

Opción A: almacenamiento de objetos compatible con S3

Sirve cualquier proveedor con API S3. Crea un bucket y una clave de acceso limitada a ese bucket, y usa el endpoint del proveedor en la URL:

# /etc/restic/env  (S3-compatible object storage)
RESTIC_REPOSITORY=s3:https://s3.example.com/example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
AWS_ACCESS_KEY_ID=REPLACE_WITH_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_SECRET_KEY
# Optional: monitoring ping URL (Step 11)
HC_PING_URL=

Opción B: SFTP a un segundo servidor

Usa otro servidor que controles, mejor en otra ubicación o con otro proveedor, con un usuario dedicado backup propietario de /srv/restic:

# /etc/restic/env  (SFTP to a second server)
RESTIC_REPOSITORY=sftp:[email protected]:/srv/restic/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
HC_PING_URL=

# One-time SSH key login for root on the VPS
ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519   # skip if the key exists
ssh-copy-id [email protected]
ssh [email protected] true      # accept the host key once

Opción C: un backend de rclone

rclone conecta restic con decenas de servicios (Backblaze B2, Google Drive, OneDrive, WebDAV y más):

# Install and configure rclone (interactive wizard, run as root)
apt install -y rclone        # Rocky/Alma: dnf install -y rclone (EPEL)
rclone config                # create a remote, for example named "offsite"

# /etc/restic/env  (any rclone backend)
RESTIC_REPOSITORY=rclone:offsite:example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
RCLONE_CONFIG=/root/.config/rclone/rclone.conf
HC_PING_URL=
Las credenciales de /etc/restic/env normalmente también permiten borrar copias, así que un atacante que se haga con el VPS podría vaciar el repositorio. Para más protección, activa el versionado o el object lock del bucket, o usa un destino de solo añadir, y no guardes la contraseña de la cuenta de almacenamiento en el servidor.

Paso 3: Crea el archivo de contraseña y el repositorio

install -d -m 0700 /etc/restic
openssl rand -base64 32 > /etc/restic/password
chmod 600 /etc/restic/password
nano /etc/restic/env          # paste one of the examples above
chmod 600 /etc/restic/env

# Load the settings into the current shell and create the repository
set -a; . /etc/restic/env; set +a
restic init
Sin la contraseña nadie puede descifrar las copias, ni siquiera tú. Copia ahora /etc/restic/password y /etc/restic/env a un gestor de contraseñas u otro lugar seguro fuera del servidor: si el VPS desaparece, son lo único que necesitas para restaurar.

Paso 4: Decide qué incluir y qué excluir

Copia la configuración y los datos, no todo el sistema operativo: reinstalar el sistema es más rápido que restaurar archivos del sistema, y los snapshots se mantienen pequeños.

# /etc/restic/include  - one path per line; delete lines that do not exist
/etc
/root
/home
/srv
/var/www
/opt
/usr/local
/var/spool/cron
/var/backups/db

# /etc/restic/excludes
/root/.cache
/home/*/.cache
**/node_modules
**/*.tmp
/var/www/*/cache
  • Incluye: /etc, los directorios personales, las raíces web, los datos de las aplicaciones, los crontabs y la carpeta de volcados.
  • Omite: /proc, /sys, /dev, /run, /tmp, los archivos de swap y las cachés. No están en la lista, así que nunca se leen.
  • Los archivos de la base de datos (/var/lib/mysql, /var/lib/postgresql) copiados con la base en marcha pueden quedar inconsistentes. Copia volcados (paso 5).
  • Docker: no copies /var/lib/docker entero; copia tus archivos compose y los volúmenes o carpetas que guardan datos.

Paso 5: Vuelca las bases de datos antes de cada copia

Este script guarda volcados comprimidos en /var/backups/db, que ya está en la lista. Ajusta MYSQL y POSTGRES a tu servidor:

#!/bin/bash
# /usr/local/sbin/db-dump.sh - consistent database dumps before each backup
set -euo pipefail
umask 077
MYSQL=yes        # yes / no
POSTGRES=no      # yes / no
OUT=/var/backups/db
mkdir -p "$OUT"

if [ "$MYSQL" = yes ]; then
  DUMP=$(command -v mariadb-dump || command -v mysqldump)
  "$DUMP" --all-databases --single-transaction --quick \
          --routines --events --triggers | gzip > "$OUT/mysql-all.sql.gz.tmp"
  mv "$OUT/mysql-all.sql.gz.tmp" "$OUT/mysql-all.sql.gz"
fi

if [ "$POSTGRES" = yes ]; then
  cd /tmp
  runuser -u postgres -- pg_dumpall | gzip > "$OUT/postgres-all.sql.gz.tmp"
  mv "$OUT/postgres-all.sql.gz.tmp" "$OUT/postgres-all.sql.gz"
fi

--single-transaction genera un volcado coherente de las tablas InnoDB sin bloquear tu web. En Debian y Ubuntu, root entra en MariaDB/MySQL por el socket local sin contraseña; si tu servidor la necesita, ponla en /root/.my.cnf (permisos 600), no en la línea de comandos.

Paso 6: Crea el script de copia

Un solo script hace los volcados, la copia, la retención y una comprobación semanal, y avisa a una URL de monitorización opcional (paso 10). Cualquier fallo lo detiene con un error, así que nada falla en silencio:

#!/bin/bash
# /usr/local/sbin/restic-backup.sh - dump databases, back up, apply retention
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set -a; . /etc/restic/env; set +a

fail() {
  [ -n "${HC_PING_URL:-}" ] && curl -fsS -m 10 --retry 3 "$HC_PING_URL/fail" >/dev/null || true
}
trap fail ERR

/usr/local/sbin/db-dump.sh

restic backup \
  --files-from /etc/restic/include \
  --exclude-file /etc/restic/excludes \
  --exclude-caches \
  --tag daily

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

# Sundays: verify the repository and read back 5% of the data
if [ "$(date +%u)" = 7 ]; then
  restic check --read-data-subset=5%
fi

if [ -n "${HC_PING_URL:-}" ]; then
  curl -fsS -m 10 --retry 3 "$HC_PING_URL" >/dev/null
fi

Da permisos de ejecución a los scripts y lanza la primera copia a mano. La primera vez sube todo; las siguientes, solo los cambios.

chmod 700 /usr/local/sbin/db-dump.sh /usr/local/sbin/restic-backup.sh
/usr/local/sbin/restic-backup.sh      # first run by hand, watch for errors
restic snapshots

Paso 7: Prográmalo con un timer de systemd (o con cron)

El timer de systemd es la opción recomendada: registra todo en el journal, recupera una ejecución perdida (Persistent=true) y baja la prioridad de CPU y disco de la tarea para que tu web siga rápida.

# /etc/systemd/system/restic-backup.service
[Unit]
Description=restic backup to off-site repository
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/restic-backup.sh
Nice=10
IOSchedulingClass=idle

# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Daily restic backup

[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=30min
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer

# Test the service once and read its log
systemctl start restic-backup.service
journalctl -u restic-backup.service -n 50 --no-pager

Si prefieres cron, usa esto en lugar del timer, no los dos a la vez:

# /etc/cron.d/restic-backup  (only if you do not use the systemd timer)
30 3 * * * root /usr/local/sbin/restic-backup.sh >> /var/log/restic-backup.log 2>&1
Ejecutar las copias de noche y con baja prioridad también cuida el disco y te ayuda a respetar las reglas de uso justo de E/S de almacenamiento.

Paso 8: Retención con restic forget --prune

restic forget decide qué snapshots se conservan y --prune elimina los datos que ya no necesita ningún snapshot. La política del script conserva:

OpciónQué conserva
--keep-daily 7el último snapshot de cada uno de los últimos 7 días
--keep-weekly 4un snapshot por semana durante 4 semanas
--keep-monthly 6un snapshot por mes durante 6 meses

Antes de fiarte de una política nueva, pruébala con --dry-run:

set -a; . /etc/restic/env; set +a
restic snapshots
# Preview what a policy would remove, without deleting anything
restic forget --dry-run --keep-daily 7 --keep-weekly 4 --keep-monthly 6
restic stats --mode raw-data

El script también ejecuta restic check cada domingo. Verifica la estructura del repositorio, y --read-data-subset=5% descarga un 5 % distinto de los datos cada vez, así que detectas cualquier corrupción antes de necesitar la copia. Puedes lanzar restic check a mano siempre que quieras más seguridad.

Paso 9: Prueba una restauración

Una copia que nunca has restaurado es solo una esperanza. Una vez al mes, restaura algo real en una carpeta temporal y compáralo:

set -a; . /etc/restic/env; set +a
restic snapshots
restic ls latest /etc/nginx

# Restore one directory to a scratch location, then compare
restic restore latest --target /tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /tmp/restore-test/etc/nginx && echo "restore OK"

# Check that the database dump is complete (last line: "-- Dump completed on ...")
restic dump latest /var/backups/db/mysql-all.sql.gz | zcat | tail -n 1
rm -rf /tmp/restore-test

Ensaya también el peor día una vez, por ejemplo en un VPS de prueba: un servidor nuevo y solo los dos archivos guardados.

# On the NEW server: install restic, then restore the two saved files
install -d -m 0700 /etc/restic
nano /etc/restic/password && nano /etc/restic/env
set -a; . /etc/restic/env; set +a

restic restore latest --target /srv/restore
rsync -a /srv/restore/var/www/ /var/www/          # copy back what you need
zcat /srv/restore/var/backups/db/mysql-all.sql.gz | mariadb     # or: mysql
Evita restic restore latest --target / en un sistema en marcha: sobrescribe archivos en uso, incluida configuración del sistema que puede no encajar en el servidor nuevo. Restaura en una carpeta aparte y copia solo lo que necesites.

Paso 10: Recibe un aviso cuando falle una copia

Las copias suelen fallar en silencio: una clave caducada, un bucket lleno, una contraseña cambiada. Un servicio tipo "dead man's switch" lo resuelve: el script hace ping a una URL tras cada ejecución correcta y recibes una alerta si falta un ping. Alójalo tú mismo (por ejemplo, el proyecto de código abierto Healthchecks) o usa cualquier servicio parecido, y añade la URL de tu comprobación a /etc/restic/env:

HC_PING_URL=https://hc.example.com/ping/REPLACE-WITH-YOUR-CHECK-ID

El script llama a la URL si todo va bien y a $HC_PING_URL/fail si hay un error. Configura un periodo de un día con unas horas de margen. Si no usas un servicio así, revisa al menos cada semana restic snapshots y journalctl -u restic-backup.service.

FAQ

¿Cuánto almacenamiento necesito?

Para el primer snapshot, más o menos el tamaño de tus datos (a menudo menos gracias a la compresión), y luego un poco cada día por los cambios. Tras unas semanas, ejecuta restic stats --mode raw-data para ver la cifra real.

restic dice que el repositorio está bloqueado. ¿Qué hago?

Una ejecución anterior se interrumpió y dejó un bloqueo obsoleto. Comprueba que no hay ningún proceso de restic en marcha (pgrep -a restic), ejecuta restic unlock y vuelve a lanzar la copia.

restic usa demasiada memoria en un plan de 512 MB. ¿Puedo reducirla?

Añade GOGC=20 a /etc/restic/env para que restic libere memoria más a menudo, mantén la lista de rutas centrada en lo importante y asegúrate de que el VPS tiene swap. Si aun así se queda sin memoria, mejora el plan desde la página del servicio. Si necesitas ayuda, abre un ticket: JUSTG ofrece soporte con IA 24/7 por ticket, y los ingenieros intervienen cuando hace falta una persona.

¿Le ha resultado útil esta respuesta?
Centro de ayuda
AlipayUnionPayVISAMastercardPayPalUSDTstripe