Skip to content
GitHub

Runbook: Disaster Recovery

Propósito: Recuperación del sistema ante fallas catastróficas (pérdida de servidor, corrupción masiva, etc.)

RTO (Recovery Time Objective): 4 horas

RPO (Recovery Point Objective): 24 horas (último backup diario)

Criticidad: 🔴 CRÍTICA - Solo ejecutar en caso de disaster real


NivelEscenarioAcción
L1Servicio caído (Orchestrator/Sevastopol)Reiniciar servicio
L2Corrupción de datos de un tenantRestore per-schema
L3Pérdida de base de datos completaFull database restore
L4Pérdida de servidor completoProvisionar nuevo servidor + restore

Cuando un servicio individual no responde pero el servidor está accesible.

  1. Verificar estado del servicio

    Terminal window
    pm2 status
  2. Revisar logs de errores

    Terminal window
    pm2 logs orchestrator --err --lines 100
  3. Reiniciar servicio

    Terminal window
    pm2 restart orchestrator
  4. Verificar recuperación

    Terminal window
    curl http://localhost:8000/health

Si el reinicio falla repetidamente, escalar a L4.


Cuando los datos de un solo tenant están corruptos pero el resto del sistema funciona.

  1. Identificar tenant afectado

    SELECT schema_name, last_access, error_count
    FROM central.tenant_health
    WHERE status = 'corrupted';
  2. Desactivar tenant temporalmente

    UPDATE central.tenants
    SET active = false
    WHERE id = '<TENANT_ID>';
  3. Localizar backup del schema

    Terminal window
    ls -lht /opt/backups/schemas/ | grep tenant_<ID>
  4. Restaurar schema individual

    Terminal window
    sudo -u postgres psql -d nostromo -c "DROP SCHEMA tenant_<ID> CASCADE;"
    gunzip -c /opt/backups/schemas/tenant_<ID>_<DATE>.sql.gz | sudo -u postgres pg_restore -d nostromo
  5. Reactivar tenant

    UPDATE central.tenants
    SET active = true
    WHERE id = '<TENANT_ID>';
  6. Verificar integridad

    SELECT COUNT(*) FROM tenant_<ID>.employees;
    SELECT COUNT(*) FROM tenant_<ID>.contracts;

Cuando se pierde acceso a toda la base de datos PostgreSQL.

  1. Detener todos los servicios

    Terminal window
    pm2 stop all
  2. Verificar estado de PostgreSQL

    Terminal window
    sudo systemctl status postgresql
    pg_isready
  3. Si PostgreSQL corrupto, recrear cluster

    Terminal window
    sudo systemctl stop postgresql
    sudo rm -rf /var/lib/postgresql/16/main/*
    sudo -u postgres /usr/lib/postgresql/16/bin/initdb -D /var/lib/postgresql/16/main
    sudo systemctl start postgresql
  4. Localizar último backup válido

    Terminal window
    ls -lht /opt/backups/ | head -20
    gunzip -t /opt/backups/<LATEST>/backup_<DATE>.sql.gz
  5. Restaurar desde backup

    Terminal window
    gunzip -c /opt/backups/<LATEST>/backup_<DATE>.sql.gz | sudo -u postgres psql
  6. Verificar restauración

    \dn
    SELECT COUNT(*) FROM central.tenants;
    SELECT COUNT(*) FROM central.users;
  7. Reiniciar servicios

    Terminal window
    pm2 start all
  8. Validar sistema completo

    Terminal window
    curl http://localhost:8000/health
    curl http://localhost:4321/

Cuando el servidor físico/VM se pierde completamente.

  1. Provisionar nuevo servidor

    • Mínimo: 4 vCPU, 8GB RAM, 100GB SSD
    • OS: Ubuntu 22.04 LTS o Debian 12
    • Acceso SSH configurado
  2. Instalar dependencias base

    Terminal window
    sudo apt update && sudo apt upgrade -y
    sudo apt install -y postgresql-16 nodejs npm nginx certbot
  3. Configurar PostgreSQL

    Terminal window
    sudo -u postgres createuser nostromo_user
    sudo -u postgres createdb nostromo
  4. Descargar backup desde storage remoto

    Terminal window
    mkdir -p /opt/backups
    aws s3 cp s3://nostromo-backups/postgres/backup_<LATEST>.sql.gz /opt/backups/
  5. Restaurar base de datos

    Terminal window
    gunzip -c /opt/backups/backup_<LATEST>.sql.gz | sudo -u postgres psql
  6. Clonar repositorios

    Terminal window
    cd /opt/nostromo
    git clone [email protected]:org/orchestrator.git
    git clone [email protected]:org/sevastopol.git
  7. Configurar variables de entorno

    Terminal window
    cp .env.production.example .env.production
    nano .env.production
  8. Instalar dependencias y build

    Terminal window
    cd /opt/nostromo/orchestrator && npm ci && npm run build
    cd /opt/nostromo/sevastopol && npm ci && npm run build
  9. Configurar PM2

    Terminal window
    pm2 start dist/server.js --name orchestrator
    pm2 start "npm run preview" --name sevastopol --cwd /opt/nostromo/sevastopol
    pm2 save
  10. Configurar Nginx y SSL

    Terminal window
    sudo certbot --nginx -d app.nostromo.cl
  11. Actualizar DNS

    Actualizar registros A en Cloudflare para apuntar a nueva IP.

  12. Validar sistema completo

    Terminal window
    curl https://app.nostromo.cl/health

URGENTE: Sistema Nostromo - Incidente en Progreso
Tipo: [L1/L2/L3/L4]
Inicio: [HORA]
Impacto estimado: [DESCRIPCION]
ETA de resolución: [HORA]
Siguiente actualización: [HORA]
UPDATE: Sistema Nostromo - En Recuperación
Estado: [EN PROGRESO/RESUELTO]
Avance: [PASO ACTUAL]
Nuevo ETA: [HORA]
RESUELTO: Sistema Nostromo - Servicio Restaurado
Duración total: [X horas]
Datos perdidos: [Ninguno / X horas de transacciones]
Acciones preventivas: [PENDIENTE POST-MORTEM]

Después de todo disaster, crear documento post-mortem:

# Post-Mortem: [FECHA] [TIPO]
## Timeline
- HH:MM - Detección
- HH:MM - Inicio respuesta
- HH:MM - Resolución
## Root Cause
[Descripción técnica de la causa raíz]
## Impacto
- Usuarios afectados: X
- Downtime total: X horas
- Datos perdidos: [Ninguno / Descripción]
## Acciones Correctivas
1. [Acción inmediata]
2. [Mejora a mediano plazo]
3. [Mejora estructural]

  • Backups diarios ejecutándose (verificar logs)
  • Backups remotos sincronizados (S3/Azure)
  • Test de restore mensual completado
  • Documentación de recovery actualizada
  • Contactos de emergencia disponibles
  • Credenciales de cloud storage accesibles


FechaVersionCambios
2026-01-181.0Runbook inicial creado