El problema#
Tenía PostgreSQL y Grafana corriendo en Docker con volúmenes persistentes. La idea de perder esos datos me mantenía despierto. Backups manuales no son confiables. Necesitaba algo automático, eficiente y verificable.
Después de probar varias opciones, me decidí por restic + S3 + cron jobs. Es directo y funciona.
Por qué restic#
Restic hace backups incrementales deduplicados. Solo envía lo que cambió. Es perfecto para volúmenes Docker que típicamente tienen pequeños cambios día a día. Además verifica integridad automáticamente.
Setup básico#
1. Instalar restic#
sudo apt-get update
sudo apt-get install restic2. Crear credenciales S3#
Necesitas acceso a un bucket S3 (o MinIO si usas self-hosted). Crea las credenciales con permisos limitados:
export AWS_ACCESS_KEY_ID="tu_access_key"
export AWS_SECRET_ACCESS_KEY="tu_secret_key"
export AWS_DEFAULT_REGION="us-east-1"Guarda esto en un archivo seguro (/root/.restic-env):
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export RESTIC_REPOSITORY="s3:https://s3.amazonaws.com/tu-bucket/backups"
export RESTIC_PASSWORD="tu_password_restic_fuerte"Permisos: chmod 600 /root/.restic-env
3. Inicializar el repositorio#
source /root/.restic-env
restic initScript de backup#
Crea /opt/backup-docker.sh:
#!/bin/bash
source /root/.restic-env
BACKUP_DIRS=(
"/var/lib/docker/volumes/postgres_data/_data"
"/var/lib/docker/volumes/grafana_data/_data"
)
TIMESTAMP=$(date +%Y-%m-%d_%H:%M:%S)
LOG_FILE="/var/log/restic-backup.log"
echo "=== Backup iniciado: $TIMESTAMP ===" >> $LOG_FILE
for dir in "${BACKUP_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "Backupeando: $dir" >> $LOG_FILE
restic backup "$dir" --tag "docker" --tag "$(date +%A)" >> $LOG_FILE 2>&1
if [ $? -eq 0 ]; then
echo "✓ Backup exitoso: $dir" >> $LOG_FILE
else
echo "✗ Error en backup: $dir" >> $LOG_FILE
# Aquí podrías enviar una notificación
fi
fi
done
echo "=== Backup completado ===" >> $LOG_FILEPermisos:
chmod +x /opt/backup-docker.shAutomatizar con cron#
Edita la crontab:
crontab -eAgrega:
# Backup diario a las 2 AM
0 2 * * * /opt/backup-docker.sh
# Verificación de integridad cada domingo a las 3 AM
0 3 * * 0 source /root/.restic-env && restic check --with-cache >> /var/log/restic-check.log 2>&1
# Limpieza de snapshots viejos cada mes
0 4 1 * * source /root/.restic-env && restic forget --keep-daily 30 --keep-weekly 12 --prune >> /var/log/restic-prune.log 2>&1Validación programada#
La línea de restic check verifica que todos los datos estén íntegros. Es lo que duermes más tranquilo:
source /root/.restic-env
restic check --with-cacheSi hay corrupción, lo sabrás. Si todo está bien, ves esto:
using backend repository stored in s3:...
checking integrity of repository
[...] 100.00% checking snapshots, keys, buckets
check successful, no errors were foundRestaurar#
Cuando lo necesites (espero que no):
source /root/.restic-env
restic restore latest --target /tmp/restoreO un snapshot específico:
restic snapshots # lista todos
restic restore <snapshot-id> --target /tmp/restoreEn producción#
Monitorea los logs:
tail -f /var/log/restic-backup.logConsidera agregar alertas si los backups fallan. Yo tengo un script que envía notificación a Discord si detecta errores.
Resultados#
Después de tres meses:
- PostgreSQL: 2.3 GB comprimido
- Grafana: 150 MB comprimido
- Almacenamiento total en S3: 1.8 GB (deduplicación en acción)
Los backups incrementales tardan entre 30 segundos y 2 minutos. Las verificaciones de integridad unos 5 minutos.
Es confiable. Dormimos mejor.
Actualizado: 2026-06-10