Tutorial: automatizar snapshots LVM y subidas incrementales a S3 con systemd timers y Restic en Debian
Hospedagem & VPS · Por Kevin Marcondes · Publicado el · 10 min de lectura
Este tutorial muestra, paso a paso, cómo automatizar snapshots LVM y subir backups incrementales a S3 con Restic en Debian, orquestando todo con systemd timers. Tendrás scripts listos, unidades systemd y consejos para verificación y recuperación. Requiere acceso root y atención a las instrucciones para evitar interrupciones.
Arquitectura del backup: snapshot LVM + Restic + S3
La estrategia combina tres piezas: snapshot en LVM para congelar un punto consistente del volumen, Restic para realizar el backup incremental y cifrado, y S3 como almacenamiento remoto. systemd se encarga del agendado y garantiza ejecución confiable, con logs centralizados en el journal.
Flujo resumido: crear snapshot LVM (copy-on-write), montar en readonly, ejecutar restic backup sobre el snapshot, desmontar y eliminar el snapshot. Durante la ventana de backup el sistema sigue operando sobre el volumen original con normalidad.
Restic almacena sólo los bloques modificados entre ejecuciones, reduciendo tráfico y tiempo. La retención se aplica con forget + prune. Si aún usas cron, migrar a timers mejora la observabilidad y robustez.
- Snapshot LVM: captura punto en el tiempo sin parar servicios.
- Restic: deduplicación, cifrado por defecto, incrementales eficientes.
- S3: almacenamiento remoto resiliente.
- systemd: planificador con logs, reintentos y dependencias.
Prerequisitos y planificación de capacidad
Antes de empezar, confirma el entorno y dimensiona el snapshot. Operaciones incorrectas en LVM pueden causar indisponibilidad o pérdida de datos. Prueba primero en un servidor de homologación.
Para la seguridad básica del servidor, revisa la lista de prácticas en la checklist de seguridad para VPS Linux.
- Debian 11/12 con acceso root.
- Paquetes: lvm2, restic.
- Volume LVM (VG/LV) con espacio libre en el VG para el snapshot (el tamaño depende de la tasa de escritura durante el backup).
- Bucket S3 accesible por red y credenciales IAM con permisos restringidos.
- Sincronización horaria (los timers dependen del reloj correcto).
- Planifica exclusiones (caches, tmp, mounts) para evitar ruido en el backup.
Bucket S3 y credenciales IAM mínimas
Crea un bucket exclusivo para backups (por proyecto/entorno) y un usuario IAM con acceso restringido sólo a ese bucket. Usa claves de acceso dedicadas. Consulta la documentación de Amazon S3 para crear el bucket y las políticas.
Restic usa la URL del repositorio en el formato s3:https://endpoint/bucket/prefix. En S3 estándar: s3:https://s3.amazonaws.com/tu-bucket/prefix. Ajusta la región según tu bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ResticBackupAccess",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions"
],
"Resource": [
"arn:aws:s3:::SEU-BUCKET"
]
},
{
"Sid": "ResticObjectsAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucketMultipartUploads",
"s3:AbortMultipartUpload"
],
"Resource": [
"arn:aws:s3:::SEU-BUCKET/*"
]
}
]
}
Instalar Restic y configurar variables seguras
Instala los paquetes y centraliza las credenciales/variables de Restic en un archivo accesible sólo por root. Protege ese archivo (0600). Crea también un archivo de exclusiones para evitar el backup de caches y puntos montados temporales.
Las variables comunes están en la tabla abajo. Adáptalas a tu entorno.
| Variable | Ejemplo | Descripción |
|---|---|---|
| RESTIC_REPOSITORY | s3:https://s3.amazonaws.com/meu-bucket/projeto1 | URL del repositorio Restic en S3 |
| RESTIC_PASSWORD | uma-senha-forte | Contraseña de cifrado del repositorio |
| AWS_ACCESS_KEY_ID | AKIA... | Clave de acceso AWS |
| AWS_SECRET_ACCESS_KEY | xxxxxxxx | Clave secreta AWS |
| AWS_DEFAULT_REGION | us-east-1 | Región del bucket |
| BACKUP_TAGS | vps-01,lvm-snapshot | Tags aplicadas a los snapshots de Restic |
set -euo pipefail
apt update && apt install -y lvm2 restic
install -d -m 0700 /etc/restic
cat > /etc/restic.env <<'EOF'
RESTIC_REPOSITORY=s3:https://s3.amazonaws.com/SEU-BUCKET/projeto1
RESTIC_PASSWORD=troque-esta-senha
AWS_ACCESS_KEY_ID=COLOQUE_SUA_CHAVE
AWS_SECRET_ACCESS_KEY=COLOQUE_SUA_SECRETA
AWS_DEFAULT_REGION=us-east-1
BACKUP_TAGS=vps-01,lvm-snapshot
EOF
chmod 0600 /etc/restic.env
# Exclusões do backup (ajuste conforme necessário)
install -d -m 0755 /etc/restic
cat > /etc/restic/excludes.txt <<'EOF'
/proc/*
/sys/*
/run/*
/tmp/*
/var/tmp/*
/var/cache/*
/mnt/*
/media/*
/swapfile
EOF
Inicializar el repositorio y validar la conexión
Inicializa el repositorio en S3 y realiza una prueba rápida de backup/consulta. Carga las variables de entorno antes de ejecutar Restic. Guarda la contraseña (RESTIC_PASSWORD): sin ella no podrás recuperar los datos.
set -euo pipefail
set -a
. /etc/restic.env
set +a
# Inicializa o repositório (executar apenas uma vez)
restic init
# Teste rápido de backup (arquivo pequeno)
restic backup --tag test /etc/hosts --exclude-file=/etc/restic/excludes.txt
# Lista snapshots para confirmar
restic snapshots
Script de backup con snapshot LVM (atómico y con limpieza)
El script abajo crea un snapshot LVM readonly, monta, ejecuta el backup incremental con Restic y elimina el snapshot garantizando limpieza vía trap. Incluye un lock simple para evitar concurrencia. Ajusta VG/LV, tamaño del snapshot y rutas según tu entorno.
Si haces backup del volumen raíz, asegura espacio libre en el VG. Para bases de datos, considera un volcado coordinado o un freeze corto del filesystem para consistencia lógica.
#!/usr/bin/env bash
set -euo pipefail
# Configuração específica do host
VG_NAME="vg0" # Volume Group
LV_NAME="root" # Logical Volume original
SNAP_SIZE="5G" # Tamanho do snapshot (depende da taxa de escrita)
MOUNT_POINT="/mnt/backup-snap"
SNAP_NAME="${LV_NAME}-snap-$(date +%Y%m%d%H%M%S)"
LOCK_FILE="/var/lock/restic-lvm-backup.lock"
exec 9>"$LOCK_FILE" || true
if ! flock -n 9; then
echo "Outro backup está em execução. Abortando." >&2
exit 1
fi
cleanup() {
set +e
if mountpoint -q "$MOUNT_POINT"; then umount "$MOUNT_POINT"; fi
if lvdisplay "/dev/${VG_NAME}/${SNAP_NAME}" >/dev/null 2>&1; then lvremove -f "/dev/${VG_NAME}/${SNAP_NAME}"; fi
}
trap cleanup EXIT
# Garante mountpoint
install -d -m 0755 "$MOUNT_POINT"
# Carrega variáveis do Restic
set -a
. /etc/restic.env
set +a
LV_PATH="/dev/${VG_NAME}/${LV_NAME}"
SNAP_PATH="/dev/${VG_NAME}/${SNAP_NAME}"
# (Opcional) Freeze curto do FS se souber o mount do LV original
# fsfreeze -f / && trap 'fsfreeze -u /; cleanup' EXIT # Exemplo perigoso; ajuste ao seu mount real
# Cria snapshot copy-on-write
lvcreate -s -L "$SNAP_SIZE" -n "$SNAP_NAME" "$LV_PATH"
# Descongela se tiver congelado
# fsfreeze -u /
# Monta snapshot como readonly
mount -o ro "$SNAP_PATH" "$MOUNT_POINT"
# Executa backup incremental com Restic
HOSTNAME_FQDN="$(hostname -f || hostname)"
ionice -c2 -n7 nice -n 10 \
restic backup \
--host "$HOSTNAME_FQDN" \
--tag "$BACKUP_TAGS" \
--exclude-file=/etc/restic/excludes.txt \
"$MOUNT_POINT"
# (Opcional) Verificação rápida de integridade do último snapshot
restic snapshots --last --compact
# Cleanup é feito no trap
Programación con systemd: service + timers (backup y retención)
Vamos a crear unidades systemd para orquestar el backup y la retención. El timer diario ejecuta el backup; el semanal aplica la retención y prune. Usa RandomizedDelaySec para evitar picos simultáneos en varios hosts.
Si aún usas cron, revisa cómo migrar en la guía Migrar cron a systemd timers.
# /usr/local/sbin/backup-lvm-restic.sh deve estar executável
chmod +x /usr/local/sbin/backup-lvm-restic.sh
# Unidade de backup
cat > /etc/systemd/system/backup-lvm-restic.service <<'EOF'
[Unit]
Description=Backup com LVM snapshot + Restic para S3
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/restic.env
ExecStart=/usr/local/sbin/backup-lvm-restic.sh
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
UMask=0077
[Install]
WantedBy=multi-user.target
EOF
# Timer diário do backup
cat > /etc/systemd/system/backup-lvm-restic.timer <<'EOF'
[Unit]
Description=Agendamento diário do backup LVM+Restic
[Timer]
OnCalendar=02:30
RandomizedDelaySec=20m
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Serviço de retenção e prune semanal
cat > /etc/systemd/system/restic-prune.service <<'EOF'
[Unit]
Description=Restic forget+prune (retenção)
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/restic.env
ExecStart=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
UMask=0077
EOF
# Timer semanal de retenção (domingo 03:30)
cat > /etc/systemd/system/restic-prune.timer <<'EOF'
[Unit]
Description=Agendamento semanal Restic prune
[Timer]
OnCalendar=Sun *-*-* 03:30:00
RandomizedDelaySec=30m
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Aplica e inicia timers
systemctl daemon-reload
systemctl enable --now backup-lvm-restic.timer
systemctl enable --now restic-prune.timer
# Primeira execução manual (opcional)
# systemctl start backup-lvm-restic.service
Verificación, restauración rápida y buenas prácticas
Valida la ejecución de los timers, revisa logs en el journal y confirma snapshots en el repositorio. Haz una restauración de muestra para probar la ruta de recuperación. Prueba antes de necesitarla.
Si centralizas logs, integra el journal con herramientas como en la guía Fluentd y Elasticsearch: logs PHP en VPS.
- Confirma timers activos y próxima ejecución.
- Revisa logs del servicio y la salida de Restic.
- Lista snapshots y tags.
- Restaura un archivo/directorio de prueba para validar claves y permisos.
- Automatiza pruebas periódicas de restore en un entorno aislado.
# Timers e próximas execuções
systemctl list-timers | grep -E 'backup-lvm-restic|restic-prune'
# Logs da última execução do backup
journalctl -u backup-lvm-restic.service -n 200 --no-pager
# Lista snapshots
set -a; . /etc/restic.env; set +a
restic snapshots --compact
# Restauração de teste (ex.: arquivo do /etc)
mkdir -p /tmp/restore-test
restic restore latest --target /tmp/restore-test --include etc/hosts
ls -l /tmp/restore-test/etc/hosts
Solución de problemas comunes
Los errores frecuentes incluyen espacio insuficiente para el snapshot, credenciales inválidas y locks pendientes en el repositorio. A continuación, síntomas y acciones. Nunca fuerces la eliminación en LVM sobre un volumen equivocado.
En sistemas con escritura intensa, aumenta SNAP_SIZE o reduce la ventana del backup. Confirma DNS/firewall para alcanzar el endpoint S3.
- Snapshot se llena/invalidado: aumenta SNAP_SIZE o reduce la actividad de escritura durante el backup.
- lvcreate falló: confirma VG/LV correctos y espacio libre en el VG (vgs/lvs).
- Permiso S3 denegado: valida la política IAM y las variables en /etc/restic.env.
- Repositorio bloqueado: usa 'restic unlock' con precaución, asegurando que no hay procesos en ejecución.
- Tiempo de backup alto: ajusta excludes, usa tags y programa fuera de horario pico.
# Diagnóstico LVM
vgs; lvs -a -o +devices
# Verificação de mountpoint do snapshot
mount | grep backup-snap || lsblk -f
# Teste de credenciais/ambiente do Restic
set -a; . /etc/restic.env; set +a
restic snapshots || echo "Verifique RESTIC_REPOSITORY e variáveis AWS"
# Remover lock do repositório com cuidado
restic unlock
# Logs detalhados
journalctl -u backup-lvm-restic.service --since "-2h" -e --no-pager
Preguntas frecuentes
¿Qué tamaño debo usar para el snapshot LVM?
Depende de la tasa de escritura durante la ventana de backup. Cuanto más cambie el volumen, mayor debe ser el snapshot (área de copy‑on‑write). Empieza con unos gigabytes y ajusta tras observar si el snapshot se llena. Monitorea las primeras ejecuciones.
¿Puedo usar endpoints compatibles con S3?
Sí, Restic funciona con APIs compatibles con S3 si indicas el endpoint en la URL del repositorio. Verifica requisitos de autenticación, región y TLS del proveedor y prueba con restic init y restic snapshots antes de automatizar.
¿Los backups de bases de datos quedan consistentes con snapshot LVM?
El snapshot LVM garantiza consistencia a nivel de bloques. Para consistencia lógica de la aplicación, realiza un dump transaccional o un freeze breve del filesystem/servicio (si está soportado) antes de lvcreate y revierte después de crear el snapshot. Evalúa el impacto en tu carga.
¿Cómo aplico retención sin perder backups útiles?
Usa restic forget con una política adecuada a tu negocio, seguida de prune. Por ejemplo, mantener 7 diarios, 4 semanales y 6 mensuales. Ajusta según RPO/RTO y siempre prueba restauraciones tras cambiar la política.
¿Es seguro mantener credenciales en /etc/restic.env?
Sí, siempre que el archivo tenga permisos restrictivos (0600) y sea accesible sólo por root. Considera separar el usuario que ejecuta Restic si no necesita privilegios elevados y rota las claves IAM periódicamente.
¿Cuánto costará almacenar en S3?
Varía según el volumen total en GB, número de objetos/versiones, operaciones y la región del bucket. Los uploads incrementales y una retención adecuada reducen coste. Consulta los precios actuales del proveedor y ajusta la política de retención.
¿Necesitas adaptar el backup a tu entorno?
Si quieres revisar la política de retención, exclusiones y ventanas de ejecución para tu carga, contáctanos y describe tu escenario.
Hablar sobre backup y automatizaciónVer también
- Tutorial: implementar Canary releases con Traefik en Docker Compose usando headers y weighted routing para despliegues graduales de aplicaciones PHP
- Tutorial: configurar HAProxy con Let's Encrypt y healthchecks para balanceo de tráfico entre contenedores Docker en VPS (paso a paso)
- Tutorial práctico: implementar mTLS entre Nginx y microservicios usando smallstep CA en Docker Compose
- Tutorial: configurar cgroup v2 y systemd ResourceControl para limitar CPU, memoria e I/O de contenedores Docker en Debian