Ir al contenido

Backups automatizados con restic y S3: Protegiendo Grafana y Listmonk en Docker

Rogelio Guerra Riverón
Autor
Rogelio Guerra Riverón
Construyendo mi propia infraestructura web desde cero. Aquí documento cada paso: servidores, redes, contenedores y lo que vaya surgiendo.

Por qué necesitas backups remotos
#

Tenía dos contenedores críticos corriendo en mi servidor doméstico: Grafana con históricos de métricas y Listmonk manejando mi lista de correos. La idea de perder esos datos me mantenía despierto. Los backups locales no son suficientes. Necesitaba algo remoto, automatizado y que no me costara una fortuna.

Restic + S3 (o compatible con S3) es la combinación que elegí. Restic es eficiente, soporta deduplicación y cifrado. S3 es accesible y barato. Aquí va lo que aprendí implementándolo.

Instalación de restic
#

Primero, instalé restic en la máquina host:

wget https://github.com/restic/restic/releases/download/v0.16.0/restic_0.16.0_linux_amd64.bz2
bzip2 -d restic_0.16.0_linux_amd64.bz2
mv restic_0.16.0_linux_amd64 /usr/local/bin/restic
chmod +x /usr/local/bin/restic
restic version

Configurar credenciales de S3
#

Creé un archivo de configuración con las credenciales. Usé Minio en mi caso (compatible con S3), pero funciona igual con AWS S3:

cat > /root/.restic-env << 'EOF'
export AWS_ACCESS_KEY_ID="tu_access_key"
export AWS_SECRET_ACCESS_KEY="tu_secret_key"
export RESTIC_REPOSITORY="s3:https://minio.dominio.local/backups/docker"
export RESTIC_PASSWORD="contraseña_fuerte_para_restic"
EOF

chmod 600 /root/.restic-env

Inicializar el repositorio
#

source /root/.restic-env
restic init

Restic crea la estructura necesaria en S3. Solo se hace una vez.

Estrategia de backup para Docker
#

Para Grafana y Listmonk necesitaba extraer los volúmenes. Creé un script que:

  1. Detiene temporalmente los contenedores
  2. Copia los volúmenes a un directorio temporal
  3. Ejecuta restic
  4. Reinicia los contenedores
cat > /usr/local/bin/docker-backup.sh << 'EOF'
#!/bin/bash
source /root/.restic-env

BACKUP_DIR="/tmp/docker-backup"
CONTAINERS=("grafana" "listmonk")

mkdir -p $BACKUP_DIR

for container in "${CONTAINERS[@]}"; do
    echo "[$(date)] Deteniendo $container..."
    docker stop $container
    
    echo "[$(date)] Backupeando volúmenes de $container..."
    docker run --rm -v ${container}-storage:/data -v $BACKUP_DIR:/backup \
        alpine tar -czf /backup/${container}.tar.gz -C /data .
    
    echo "[$(date)] Iniciando $container..."
    docker start $container
done

echo "[$(date)] Ejecutando restic backup..."
restic backup $BACKUP_DIR --tag="docker-containers" --cleanup-cache

echo "[$(date)] Backup completado"
echo "[$(date)] Limpiando archivos temporales..."
rm -rf $BACKUP_DIR

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune
EOF

chmod +x /usr/local/bin/docker-backup.sh

Automatizar con cron
#

# Backup diario a las 2 AM
0 2 * * * /usr/local/bin/docker-backup.sh >> /var/log/docker-backup.log 2>&1

Verificar y restaurar
#

Para estar seguro, verifico regularmente:

source /root/.restic-env
restic snapshots
restic check

Para restaurar en caso de desastre:

source /root/.restic-env
restic restore latest --target /tmp/restore-point

Después extraería los tar.gz en los volúmenes correspondientes.

Lo que aprendí
#

  • No confíes solo en backups locales. Un fallo del disco afecta todo.
  • Cifra los datos en tránsito. Restic lo hace automáticamente.
  • Verifica los backups. He visto casos donde fallaban sin aviso.
  • Ten política de retención. No necesito backups de hace 2 años.
  • Monitorea los logs. Agrego alertas si el backup falla.

Consideraciones finales
#

Esta configuración me permite dormir tranquilo. Los backups corren automaticamente, están cifrados, deduplicados y almacenados remotamente. El único punto débil es confiar en que S3 no falla, pero eso es aceptable para un servidor doméstico.

Si usas AWS S3 puro, el costo es mínimo. Si usas Minio o Backblaze B2, aún mejor.