Ir al contenido

Automatizar backups incrementales de volúmenes Docker en PostgreSQL con restic y verificación en NAS

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.

El problema
#

Tenía PostgreSQL corriendo en Docker con volúmenes que contenían datos críticos. Los backups manuales no escalan y respaldar todo cada vez es ineficiente. Necesitaba algo automatizado, incremental y que verificara que los datos llegaran bien al NAS.

Por qué restic
#

Restic maneja snapshots incrementales nativamente, comprime, cifra y permite verificar la integridad de los backups remotos sin descargar todo. Perfecto para un servidor doméstico donde el ancho de banda importa.

Prerequisitos
#

  • Docker con PostgreSQL corriendo
  • NAS accesible por SSH o SMB
  • restic instalado en el host
  • pg_dump o acceso al contenedor PostgreSQL
  • Script de automatización (systemd timer o cron)

Paso 1: Preparar el volumen de datos
#

Primero, identifico dónde está el volumen de PostgreSQL:

docker volume inspect postgres_data

Esto me muestra la ruta. En mi caso: /var/lib/docker/volumes/postgres_data/_data

Paso 2: Configurar acceso al NAS
#

Monto el NAS en el host. Uso SSH con restic:

export RESTIC_REPOSITORY="sftp:usuario@192.168.1.100:/backups/postgres"
export RESTIC_PASSWORD="contraseña-fuerte"

Guardo estas variables en un archivo seguro:

cat > /etc/restic/env.sh << 'EOF'
export RESTIC_REPOSITORY="sftp:usuario@192.168.1.100:/backups/postgres"
export RESTIC_PASSWORD="tu-password"
EOF

chmod 600 /etc/restic/env.sh

Paso 3: Crear script de backup
#

El script hace tres cosas: dump de la BD, backup con restic y verificación:

#!/bin/bash
set -e

source /etc/restic/env.sh

POSTGRES_CONTAINER="postgres"
BACKUP_DIR="/tmp/pg_backups"
LOG_FILE="/var/log/restic-postgres.log"

# Crear directorio temporal
mkdir -p $BACKUP_DIR

# Dump de PostgreSQL
docker exec $POSTGRES_CONTAINER pg_dump -U postgres nombrebd | \
  gzip > $BACKUP_DIR/db_$(date +%Y%m%d_%H%M%S).sql.gz

# Backup incremental con restic
echo "[$(date)] Iniciando backup..." >> $LOG_FILE
restic backup $BACKUP_DIR \
  --tag postgres \
  --tag incremental \
  2>&1 >> $LOG_FILE

# Verificar integridad
echo "[$(date)] Verificando integridad..." >> $LOG_FILE
restic check --read-data 2>&1 >> $LOG_FILE

if [ $? -eq 0 ]; then
  echo "[$(date)] Backup verificado correctamente" >> $LOG_FILE
  rm -rf $BACKUP_DIR
else
  echo "[$(date)] ERROR: Verificación fallida" >> $LOG_FILE
  exit 1
fi

Lo guardo en /usr/local/bin/backup-postgres.sh y lo hago ejecutable:

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

Paso 4: Automatizar con systemd timer
#

Creo un servicio y un timer para ejecutar diariamente:

cat > /etc/systemd/system/restic-postgres.service << 'EOF'
[Unit]
Description=Restic Backup PostgreSQL
After=docker.service
Wants=restic-postgres.timer

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-postgres.sh
StandardOutput=journal
StandardError=journal
EOF
cat > /etc/systemd/system/restic-postgres.timer << 'EOF'
[Unit]
Description=Restic PostgreSQL Timer
Requires=restic-postgres.service

[Timer]
OnCalendar=daily
OnCalendar=03:00
Persistent=true

[Install]
WantedBy=timers.target
EOF

Activo los timers:

systemctl daemon-reload
systemctl enable --now restic-postgres.timer

Paso 5: Monitorear y verificar
#

Chequeo el estado:

systemctl status restic-postgres.timer
journalctl -u restic-postgres.service -n 50

Para ver snapshots disponibles en el NAS:

restic snapshots

Verificación periódica
#

Cada mes ejecuto una verificación completa de lectura:

restic check --read-data-subset=10%

Conclusión
#

Con esto tengo backups incrementales diarios, cifrados, verificados automáticamente y almacenados en el NAS. El overhead es mínimo porque restic solo sube lo que cambió. Si algo falla, systemd me avisa en el log y puedo investigar.

El punto crítico: restic verifica que los datos se escribieron bien sin descargar todo. Eso vale oro en un backup.