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.