Automatizar backups incrementales de PostgreSQL en Docker con cron y verificación en Wireguard

El problema

Tengo un PostgreSQL corriendo en Docker en mi servidor doméstico. Los datos son importantes. Los backups manuales son un desastre garantizado. Necesitaba algo automatizado, incremental y verificable sin exponer el servidor a internet.

La solución

Combiné cron, Docker, pg_dump y Wireguard para crear un sistema de backups que se ejecuta solo, verifica su integridad y me avisa si algo falla.

Paso 1: Script de backup incremental

Primero, creé un script que genera backups con marca de tiempo y usa hard links para no duplicar datos innecesarios:

#!/bin/bash

BACKUP_DIR="/mnt/backups/postgresql"
DB_CONTAINER="postgres-container"
DB_NAME="tu_base_datos"
FULL_BACKUP_DAY=0  # Domingo
RETENTION_DAYS=30

mkdir -p "$BACKUP_DIR"

CURRENT_DAY=$(date +%u)
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)

if [ "$CURRENT_DAY" -eq "$FULL_BACKUP_DAY" ]; then
    BACKUP_FILE="$BACKUP_DIR/full_backup_$BACKUP_DATE.sql.gz"
    docker exec $DB_CONTAINER pg_dump -U postgres $DB_NAME | gzip > "$BACKUP_FILE"
    echo "Full backup creado: $BACKUP_FILE"
else
    LAST_FULL=$(ls -t "$BACKUP_DIR"/full_backup_*.sql.gz 2>/dev/null | head -1)
    BACKUP_FILE="$BACKUP_DIR/incr_backup_$BACKUP_DATE.sql.gz"
    docker exec $DB_CONTAINER pg_dump -U postgres $DB_NAME | gzip > "$BACKUP_FILE"
    echo "Backup incremental creado: $BACKUP_FILE"
fi

# Calcular hash para verificación
sha256sum "$BACKUP_FILE" > "$BACKUP_FILE.sha256"

# Limpiar backups antiguos
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete

echo "Backup completado exitosamente"

Guardé esto en /opt/backup-scripts/pg_backup.sh con permisos de ejecución:

chmod +x /opt/backup-scripts/pg_backup.sh

Paso 2: Configurar cron

Agregué la tarea a crontab para ejecutarse diariamente a las 2 AM:

crontab -e
0 2 * * * /opt/backup-scripts/pg_backup.sh >> /var/log/pg_backup.log 2>&1

Paso 3: Script de verificación con Wireguard

Ahora necesitaba verificar la integridad de los backups desde otra máquina a través de Wireguard. Creé un script de verificación:

#!/bin/bash

BACKUP_DIR="/mnt/backups/postgresql"
LOG_FILE="/var/log/backup_verify.log"

{
    echo "=== Verificación de backups - $(date) ==="

    for backup in "$BACKUP_DIR"/*.sql.gz; do
        if [ -f "$backup.sha256" ]; then
            if sha256sum -c "$backup.sha256" > /dev/null 2>&1; then
                echo "[OK] $backup"
            else
                echo "[ERROR] Checksum fallido: $backup"
                # Aquí podrías enviar una alerta
            fi
        fi
    done
} >> "$LOG_FILE"

Lo dejé en /opt/backup-scripts/verify_backups.sh y lo ejecuto semanalmente:

0 3 * * 0 /opt/backup-scripts/verify_backups.sh

Paso 4: Acceso seguro vía Wireguard

En mi servidor doméstico, solo la VPN de Wireguard tiene acceso a la ruta de backups. En el cliente Wireguard:

  1. Me conecto a la VPN
  2. Puedo acceder al servidor por su IP de Wireguard
  3. Ejecuto la verificación de forma segura sin exponer nada a internet
ssh usuario@10.0.0.2 "sudo /opt/backup-scripts/verify_backups.sh"

Monitoreo

Configuré alertas básicas editando el script de backup para notificar errores:

if [ $? -ne 0 ]; then
    echo "Backup fallido" | mail -s "Error en backup PostgreSQL" mi@email.com
fi

Lo que aprendí

  • Los backups automáticos sin verificación son apenas mejores que nada
  • Hard links ahorran espacio pero complican las cosas. Acabé usando compresión simple
  • Wireguard es extremadamente util para acceso seguro sin VPN tradicionales
  • Ejecutar backups a las 2 AM evita picos de carga

He estado usando esta setup 6 meses. Funciona sin intervención. Los backups se crean, se verifican y se limpian solos. Eso es exactamente lo que quería.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio