Saltar a contenido

Backup

La estrategia de backup protege dos activos críticos: la base de datos PostgreSQL (usuarios, sesiones, configuración de realms) y los archivos de configuración del entorno. Un backup correcto permite restaurar la plataforma completa en un VPS limpio en menos de 30 minutos.

Qué hacer backup

Activo Herramienta Frecuencia Retención
PostgreSQL (keycloak DB) pg_dump Diario 02:00 UTC 7 días
Realm export (JSON) Keycloak Admin API Diario 02:30 UTC 7 días
Archivos de configuración tar Semanal o ante cada cambio 4 versiones
Secretos / .env Encriptado + offsite Semanal 4 versiones

Script de backup completo

#!/bin/bash
# /opt/identity-platform/scripts/backup.sh

set -euo pipefail

BACKUP_DIR="/var/backups/identity-platform"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="${BACKUP_DIR}/${TIMESTAMP}"
KEYCLOAK_URL="http://localhost:8080"
REALM_LIST=("realm-internal" "realm-partners")

# Cargar variables de entorno
source /opt/identity-platform/.env

mkdir -p "${BACKUP_PATH}"

echo "[$(date)] Iniciando backup..."

# 1. Backup de PostgreSQL
echo "[$(date)] Backup PostgreSQL..."
docker exec identity-platform-postgres-1 \
  pg_dump -U "${KC_DB_USER}" "${KC_DB_NAME}" | \
  gzip > "${BACKUP_PATH}/keycloak-db.sql.gz"

echo "[$(date)] PostgreSQL OK: $(du -sh ${BACKUP_PATH}/keycloak-db.sql.gz | cut -f1)"

# 2. Export de realms vía Admin API
echo "[$(date)] Export de realms..."
ADMIN_TOKEN=$(curl -s -X POST \
  "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \
  -d "grant_type=password&client_id=admin-cli" \
  -d "username=${KC_ADMIN}&password=${KC_ADMIN_PASSWORD}" | \
  jq -r '.access_token')

for REALM in "${REALM_LIST[@]}"; do
  curl -s -H "Authorization: Bearer ${ADMIN_TOKEN}" \
    "${KEYCLOAK_URL}/admin/realms/${REALM}" | \
    jq . > "${BACKUP_PATH}/realm-${REALM}.json"
  echo "[$(date)] Realm ${REALM} exportado"
done

# 3. Backup de configuración
echo "[$(date)] Backup de configuración..."
tar -czf "${BACKUP_PATH}/config.tar.gz" \
  --exclude='.env' \
  /opt/identity-platform/

# 4. Encriptar .env (nunca guardar en texto plano)
gpg --batch --yes \
  --passphrase "${BACKUP_PASSPHRASE}" \
  --symmetric \
  --output "${BACKUP_PATH}/env.gpg" \
  /opt/identity-platform/.env

echo "[$(date)] Configuración OK"

# 5. Calcular checksums
sha256sum "${BACKUP_PATH}"/* > "${BACKUP_PATH}/checksums.sha256"

# 6. Eliminar backups más antiguos de 7 días
find "${BACKUP_DIR}" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +

echo "[$(date)] Backup completado en ${BACKUP_PATH}"
echo "[$(date)] Tamaño total: $(du -sh ${BACKUP_PATH} | cut -f1)"

Automatizar con cron

# crontab -e
# Backup diario a las 02:00 UTC
0 2 * * * /opt/identity-platform/scripts/backup.sh >> /var/log/identity-backup.log 2>&1

Transferencia a almacenamiento remoto

# Al final del script de backup, sincronizar con servidor remoto
rsync -az --delete \
  "${BACKUP_DIR}/" \
  backup-user@backup-server.example.com:/backups/identity-platform/

# Alternativa con rclone (S3, GCS, Azure Blob, etc.)
rclone sync "${BACKUP_DIR}/" "s3:my-bucket/identity-backups/" \
  --log-level INFO \
  --log-file /var/log/rclone-backup.log

Verificación del backup

Verificar que el backup es válido al menos una vez al mes:

# Verificar checksums
cd /var/backups/identity-platform/ULTIMO_BACKUP/
sha256sum -c checksums.sha256

# Verificar que el dump SQL es legible
zcat keycloak-db.sql.gz | head -20

# Verificar que el JSON del realm es válido
jq . realm-realm-internal.json > /dev/null && echo "JSON válido"

# Test de restauración en entorno de prueba (mensual)
# Ver procedimiento completo en: /docs/operations/restore.md

Nunca guardar .env sin encriptar en el backup

El archivo .env contiene secretos críticos (contraseña de admin, contraseña de BD, client secrets). Siempre encriptarlo con GPG o equivalente antes de incluirlo en el backup. La passphrase de encriptación debe estar en un gestor de secretos separado (ej: Bitwarden, 1Password, Vault).

Verificar que el backup funciona antes de necesitarlo

Ejecuta una restauración de prueba en un entorno aislado al menos una vez al mes. El peor momento para descubrir que el backup está corrupto es durante un incidente real.

Alerta si el backup falla

Agrega al script de backup una notificación cuando falle:

# Al inicio del script
trap 'echo "BACKUP FALLIDO: $?" | mail -s "ALERTA: Backup Identity Platform" ops@example.com' ERR