diff --git a/00_VISION/filosofia.md b/00_VISION/filosofia.md index bfc90c7..7b82648 100644 --- a/00_VISION/filosofia.md +++ b/00_VISION/filosofia.md @@ -101,5 +101,18 @@ VALORES → OBJETIVOS → IMÁGENES IA → CURACIÓN HUMANA → LO QUE SOBREVIVE Cada instancia: - Tiene su propio bucket de almacenamiento - Puede renombrar sus agentes -- Opera de forma descentralizada -- Se conecta a servicios compartidos (GRACE, THE FACTORY, CIRCLE) +- **Opera de forma autónoma** (no depende de ARCHITECT en runtime) +- Tiene su propio gestor de secretos (Vaultwarden) +- Hace sus propios backups a R2 + +### Servicios Compartidos (Opcionales) + +Las instancias **pueden** conectarse a servicios GPU compartidos: + +| Servicio | Función | Requerido | +|----------|---------|-----------| +| GRACE | Extracción IA | Opcional | +| THE FACTORY | Generación | Opcional | +| CIRCLE | Colaboración | Opcional | + +> **Nota:** Si los servicios compartidos no están disponibles, la instancia sigue operando. Solo las funciones de IA estarán limitadas. diff --git a/01_ARQUITECTURA/overview.md b/01_ARQUITECTURA/overview.md index e918db3..f716db9 100644 --- a/01_ARQUITECTURA/overview.md +++ b/01_ARQUITECTURA/overview.md @@ -5,24 +5,37 @@ --- +## Principio Fundamental + +> **ARCHITECT es el constructor. DECK y CORP son instancias autónomas.** + +- **ARCHITECT**: Construye, despliega, coordina. NO es dependencia runtime. +- **DECK/CORP**: Operan independientemente. Funcionan si ARCHITECT está caído. + +--- + ## Diagrama General ``` ┌─────────────────────────────────────────────────────────────────────────┐ -│ CAPA DE COORDINACIÓN │ +│ CAPA DE CONSTRUCCIÓN (solo deploy/dev) │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ ARCHITECT (69.62.126.110) │ │ │ │ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌───────────────┐ │ │ │ │ │PostgreSQL│ │ Gitea │ │Orchestrator│ │ Infisical │ │ │ -│ │ │ central │ │ 25 repos │ │ v5 │ │ Secrets │ │ │ +│ │ │ contexto │ │ 25 repos │ │ v5 │ │ (master) │ │ │ │ │ └──────────┘ └──────────┘ └────────────┘ └───────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Rol: Construcción, deployment, gestión central de secretos │ +│ NO es dependencia runtime de las instancias │ └─────────────────────────────────────────────────────────────────────────┘ │ │ │ + deploy │ │ │ deploy ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ -│ CAPA DE SERVIDORES │ +│ CAPA DE INSTANCIAS (autónomas) │ │ │ │ ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ │ │ DECK │ │ CORP │ │ HST │ │ diff --git a/04_SEGURIDAD/secretos.md b/04_SEGURIDAD/secretos.md index 355b789..bf5f943 100644 --- a/04_SEGURIDAD/secretos.md +++ b/04_SEGURIDAD/secretos.md @@ -5,205 +5,266 @@ --- -## Estado Actual: Triple Gestión +## Arquitectura de Secretos -**PROBLEMA CRÍTICO:** Actualmente existen tres fuentes de secretos sin sincronización. +### Principio Fundamental + +> **DECK y CORP son instancias autónomas. Deben operar independientemente de ARCHITECT.** + +ARCHITECT es el constructor/coordinador. DECK y CORP son instancias diseñadas para trabajar solas. + +### Modelo de Gestión ``` ┌─────────────────────────────────────────────────────────────────┐ -│ FUENTES DE SECRETOS │ +│ ARCHITECT │ +│ (Constructor) │ │ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Infisical │ │ creds_* │ │ .env │ │ -│ │ (central) │ │ (PostgreSQL)│ │ (archivos) │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ ❌ SIN SINCRONIZACIÓN - Riesgo de inconsistencia │ │ -│ └─────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────┘ +│ ┌──────────────┐ │ +│ │ Infisical │ ← Gestión centralizada │ +│ │ :8082 │ Single source of truth │ +│ └──────┬───────┘ │ +│ │ │ +└───────────────────────────┼─────────────────────────────────────┘ + │ + sync/push │ (en deploy o periódico) + │ + ┌────────────────┴────────────────┐ + ▼ ▼ +┌──────────────────────┐ ┌──────────────────────┐ +│ DECK │ │ CORP │ +│ (Instancia) │ │ (Instancia) │ +│ │ │ │ +│ ┌──────────────┐ │ │ ┌──────────────┐ │ +│ │ Vaultwarden │ │ │ │ Vaultwarden │ │ +│ │ :8085 │ │ │ │ :8081 │ │ +│ └──────┬───────┘ │ │ └──────┬───────┘ │ +│ │ │ │ │ │ +│ ▼ │ │ ▼ │ +│ CLARA, ALFRED │ │ MARGARET, JARED │ +│ leen de aquí │ │ MASON, FELDMAN │ +│ │ │ leen de aquí │ +└──────────────────────┘ └──────────────────────┘ +``` + +### Gestores por Servidor + +| Servidor | Gestor | Puerto | Rol | +|----------|--------|--------|-----| +| ARCHITECT | Infisical | 8082 | Gestión central, source of truth | +| DECK | Vaultwarden | 8085 | Operación autónoma DECK | +| CORP | Vaultwarden | 8081 | Operación autónoma CORP | + +--- + +## Flujo de Secretos + +### Administración (en ARCHITECT) + +``` +Administrador + │ + ▼ +┌─────────────┐ +│ Infisical │ ← Crear/modificar/rotar secretos aquí +│ (central) │ +└─────────────┘ +``` + +### Sincronización (ARCHITECT → Instancias) + +``` +Infisical (ARCHITECT) + │ + │ Script de sync / deploy + │ + ├────────────────┬────────────────┐ + ▼ ▼ ▼ +Vaultwarden Vaultwarden (otras instancias + DECK CORP futuras) +``` + +### Operación (en cada instancia) + +``` +┌──────────────────────────────────────┐ +│ DECK │ +│ │ +│ CLARA ──────► Vaultwarden ◄─────── ALFRED +│ :8085 │ +│ │ +│ ✅ No depende de ARCHITECT │ +│ ✅ Opera si ARCHITECT está caído │ +└──────────────────────────────────────┘ ``` --- -## Fuente 1: Infisical +## Estado Actual: Problema -**URL:** http://localhost:8082 (ARCHITECT) -**Estado:** Operativo +**Triple gestión sin sincronización:** -### Configuración +| Fuente | Ubicación | Estado | +|--------|-----------|--------| +| Infisical | ARCHITECT :8082 | Parcialmente usado | +| creds_* | PostgreSQL ARCHITECT | Activo | +| .env | /opt/*/.env en cada servidor | Activo, **permisos 644** | -```bash -# Acceso a Infisical -infisical login -infisical secrets --env=prod -``` - -### Ventajas -- Centralizado -- Versionado -- Auditable -- SDK para múltiples lenguajes - -### Uso Actual -- Parcial - no todos los servicios lo usan +**Problemas:** +- Secretos duplicados en múltiples lugares +- Sin sincronización entre fuentes +- .env legibles por todos (644) +- Vaultwarden de DECK/CORP no integrados --- -## Fuente 2: Tablas creds_* (PostgreSQL) - -**Base de datos:** architect -**Estado:** Activo - -### Tablas - -| Tabla | Contenido | -|-------|-----------| -| creds_ia | APIs de IA (OpenAI, Anthropic, etc.) | -| creds_runpod | API keys de RunPod | -| creds_r2 | Credenciales Cloudflare R2 | -| creds_gitea | Tokens Gitea | -| creds_mail | Credenciales SMTP | -| creds_apis | APIs externas varias | - -### Schema Típico - -```sql -CREATE TABLE creds_ia ( - id SERIAL PRIMARY KEY, - servicio VARCHAR(50) NOT NULL, - api_key TEXT NOT NULL, - descripcion TEXT, - activo BOOLEAN DEFAULT true, - created_at TIMESTAMP DEFAULT NOW(), - updated_at TIMESTAMP DEFAULT NOW() -); -``` - -### Acceso - -```sql --- Consultar credenciales -sudo -u postgres psql -d architect -c "SELECT servicio, descripcion FROM creds_ia;" -``` - ---- - -## Fuente 3: Archivos .env - -**Ubicaciones:** -- /opt/clara/.env -- /opt/alfred/.env -- /opt/margaret/.env -- /opt/mason/.env -- /opt/feldman/.env - -### ALERTA CRÍTICA - -``` -Permisos actuales: 644 (legibles por todos) -Permisos correctos: 600 (solo propietario) -``` - -### Contenido Típico - -```bash -# Ejemplo .env -DB_HOST=localhost -DB_PORT=5432 -DB_NAME=corp -DB_USER=margaret -DB_PASSWORD=secreto_aqui # ⚠️ Expuesto si 644 - -R2_ACCESS_KEY=access_key_aqui -R2_SECRET_KEY=secret_key_aqui # ⚠️ Expuesto si 644 -``` - ---- - -## Decisión D-001: Migración a Infisical +## Decisión D-001: Arquitectura de Secretos ### Objetivo -Infisical como **única fuente de verdad** para todos los secretos. -### Plan de Migración +1. **Infisical** (ARCHITECT): Única fuente de verdad para administración +2. **Vaultwarden** (DECK/CORP): Gestores locales para operación autónoma +3. **Sync**: Mecanismo de propagación Infisical → Vaultwarden + +### División de Responsabilidades + +| Tipo de Secreto | Gestión en | Operación en | +|-----------------|------------|--------------| +| API keys externas (OpenAI, etc.) | Infisical | Vaultwarden local | +| R2 credentials | Infisical | Vaultwarden local | +| Gitea tokens | Infisical | Vaultwarden local | +| DB password DECK | Infisical | Vaultwarden DECK | +| DB password CORP | Infisical | Vaultwarden CORP | +| Tokens internos DECK | Infisical | Vaultwarden DECK | +| Tokens internos CORP | Infisical | Vaultwarden CORP | + +### Flujo de Trabajo ``` -Fase 1: Inventario -├── Catalogar todos los secretos en creds_* -├── Catalogar todos los secretos en .env -└── Identificar duplicados/inconsistencias - -Fase 2: Centralización -├── Migrar todos los secretos a Infisical -├── Organizar por proyecto/ambiente -└── Establecer políticas de acceso - -Fase 3: Actualización de Servicios -├── CLARA: Usar Infisical SDK -├── MARGARET: Usar Infisical SDK -├── MASON: Usar Infisical SDK -├── FELDMAN: Usar Infisical SDK -└── ALFRED/JARED: Usar Infisical SDK - -Fase 4: Deprecación -├── Eliminar archivos .env -├── Marcar creds_* como "solo referencia" -└── Documentar proceso de rotación -``` - -### Implementación con SDK - -```python -from infisical_client import InfisicalClient - -client = InfisicalClient( - host="http://localhost:8082", - token=INFISICAL_TOKEN -) - -# Obtener secreto -db_password = client.get_secret( - secret_name="DB_PASSWORD", - project_id="tzzr", - environment="production" -) +1. Admin modifica secreto en Infisical (ARCHITECT) + │ + ▼ +2. Script de sync detecta cambio + │ + ▼ +3. Propaga a Vaultwarden de DECK y/o CORP + │ + ▼ +4. Servicios locales usan Vaultwarden local + │ + ▼ +5. ARCHITECT puede caer → DECK/CORP siguen operando ``` --- -## Rotación de Secretos +## Plan de Migración -### Política Propuesta - -| Tipo | Frecuencia | Responsable | -|------|------------|-------------| -| API Keys externas | 90 días | Orchestrator | -| Contraseñas DB | 180 días | DBA | -| SSH Keys | 365 días | SysAdmin | -| Tokens Gitea | 180 días | DevOps | - -### Proceso de Rotación +### Fase 1: Inventario ``` -1. Generar nuevo secreto -2. Actualizar en Infisical -3. Desplegar servicios afectados -4. Verificar funcionamiento -5. Revocar secreto anterior -6. Documentar en changelog +├── Catalogar todos los secretos en creds_* +├── Catalogar todos los secretos en .env +├── Identificar duplicados/inconsistencias +└── Mapear qué secretos necesita cada instancia +``` + +### Fase 2: Centralización en Infisical + +``` +├── Migrar todos los secretos a Infisical +├── Organizar por instancia (DECK, CORP) +├── Establecer políticas de acceso +└── Documentar cada secreto +``` + +### Fase 3: Configurar Vaultwarden en Instancias + +``` +├── DECK: Configurar Vaultwarden :8085 +│ ├── Crear organización "DECK" +│ ├── Importar secretos de DECK desde Infisical +│ └── Configurar acceso para servicios +│ +└── CORP: Configurar Vaultwarden :8081 + ├── Crear organización "CORP" + ├── Importar secretos de CORP desde Infisical + └── Configurar acceso para servicios +``` + +### Fase 4: Implementar Sync + +``` +├── Crear script de sincronización +│ └── infisical export → vaultwarden import +├── Configurar trigger (manual, cron, o webhook) +└── Probar sync en ambas direcciones +``` + +### Fase 5: Actualizar Servicios + +``` +├── CLARA: Leer de Vaultwarden DECK +├── ALFRED: Leer de Vaultwarden DECK +├── MARGARET: Leer de Vaultwarden CORP +├── JARED: Leer de Vaultwarden CORP +├── MASON: Leer de Vaultwarden CORP +└── FELDMAN: Leer de Vaultwarden CORP +``` + +### Fase 6: Deprecación + +``` +├── Eliminar archivos .env +├── Marcar creds_* como "solo referencia histórica" +└── Documentar proceso completo +``` + +--- + +## Implementación + +### Lectura desde Vaultwarden (Python) + +```python +import requests + +VAULTWARDEN_URL = "http://localhost:8085" # DECK +# VAULTWARDEN_URL = "http://localhost:8081" # CORP + +def get_secret(name: str) -> str: + """Obtiene secreto de Vaultwarden local.""" + # Implementar según API de Vaultwarden/Bitwarden + pass +``` + +### Script de Sync (Infisical → Vaultwarden) + +```bash +#!/bin/bash +# /opt/scripts/sync_secrets.sh + +# Exportar desde Infisical +infisical export --env=deck --format=json > /tmp/deck_secrets.json +infisical export --env=corp --format=json > /tmp/corp_secrets.json + +# Importar a Vaultwarden DECK +ssh deck 'bw import --format json /tmp/deck_secrets.json' + +# Importar a Vaultwarden CORP +ssh corp 'bw import --format json /tmp/corp_secrets.json' + +# Cleanup +rm /tmp/*_secrets.json ``` --- ## Mitigación Inmediata -### Paso 1: Permisos .env +### Paso 1: Permisos .env (URGENTE) ```bash -# Ejecutar en todos los servidores - # DECK ssh -i ~/.ssh/tzzr root@72.62.1.113 'chmod 600 /opt/clara/.env /opt/alfred/.env' @@ -211,82 +272,73 @@ ssh -i ~/.ssh/tzzr root@72.62.1.113 'chmod 600 /opt/clara/.env /opt/alfred/.env' ssh -i ~/.ssh/tzzr root@92.112.181.188 'chmod 600 /opt/margaret/.env /opt/mason/.env /opt/feldman/.env' ``` -### Paso 2: Auditoría +### Paso 2: Verificar Vaultwarden ```bash -# Verificar permisos -ls -la /opt/*/.env +# DECK +curl -s http://72.62.1.113:8085/api/health -# Buscar secretos expuestos -grep -r "password\|secret\|key" /opt/*/ 2>/dev/null +# CORP +curl -s http://92.112.181.188:8081/api/health ``` --- -## Inventario de Secretos +## Rotación de Secretos -### APIs de IA +### Política -| Servicio | Ubicación Actual | Notas | -|----------|------------------|-------| -| OpenAI | creds_ia | GPT-4 | -| Anthropic | creds_ia | Claude | -| Replicate | creds_ia | Modelos varios | -| RunPod | creds_runpod | GRACE, PENNY, FACTORY | +| Tipo | Frecuencia | Responsable | +|------|------------|-------------| +| API Keys externas | 90 días | Admin vía Infisical | +| Contraseñas DB | 180 días | Admin vía Infisical | +| SSH Keys | 365 días | Admin vía Infisical | +| Tokens Gitea | 180 días | Admin vía Infisical | -### Infraestructura +### Proceso -| Servicio | Ubicación Actual | Notas | -|----------|------------------|-------| -| PostgreSQL | .env + creds_* | Múltiples usuarios | -| R2/Cloudflare | .env + creds_r2 | Access + Secret key | -| Gitea | .env + creds_gitea | Read + Write tokens | -| SMTP | creds_mail | Mailcow | - -### Servicios Externos - -| Servicio | Ubicación Actual | Notas | -|----------|------------------|-------| -| Stripe | creds_apis | (si aplica) | -| Twilio | creds_apis | (si aplica) | -| AWS | creds_apis | (si aplica) | - ---- - -## Verificación de Seguridad - -### Checklist Diario - -- [ ] Permisos .env son 600 -- [ ] No hay secretos en logs -- [ ] No hay secretos en commits git -- [ ] Infisical accesible - -### Comandos de Verificación - -```bash -# Verificar permisos -find /opt -name ".env" -exec ls -la {} \; - -# Buscar secretos en git history -git log -p | grep -i "password\|secret\|key\|token" - -# Verificar Infisical -curl -s http://localhost:8082/api/v1/health +``` +1. Rotar en Infisical (ARCHITECT) +2. Ejecutar sync a Vaultwarden (DECK/CORP) +3. Verificar servicios operando +4. Documentar rotación ``` --- -## Buenas Prácticas +## Verificación -### DO (Hacer) -- Usar Infisical para todos los secretos nuevos -- Rotar secretos según política -- Auditar accesos regularmente -- Cifrar secretos en reposo +### Checklist -### DON'T (No Hacer) -- Hardcodear secretos en código -- Commitear .env a repositorios -- Compartir secretos por chat/email -- Usar el mismo secreto en múltiples servicios +- [ ] Infisical operativo en ARCHITECT +- [ ] Vaultwarden operativo en DECK (:8085) +- [ ] Vaultwarden operativo en CORP (:8081) +- [ ] Sync configurado y probado +- [ ] Servicios leen de Vaultwarden local +- [ ] .env eliminados o con permisos 600 +- [ ] DECK opera si ARCHITECT cae +- [ ] CORP opera si ARCHITECT cae + +### Test de Autonomía + +```bash +# 1. Detener ARCHITECT (simulado) +# 2. Verificar DECK sigue operando +curl http://72.62.1.113:5051/health # CLARA + +# 3. Verificar CORP sigue operando +curl http://92.112.181.188:5051/health # MARGARET +``` + +--- + +## Resumen + +| Componente | Rol | +|------------|-----| +| **Infisical (ARCHITECT)** | Gestión centralizada, source of truth | +| **Vaultwarden (DECK)** | Operación autónoma instancia personal | +| **Vaultwarden (CORP)** | Operación autónoma instancia empresarial | +| **Sync** | Propagación de cambios | + +**Principio clave:** Las instancias (DECK, CORP) nunca dependen de ARCHITECT en runtime. diff --git a/05_OPERACIONES/backup-recovery.md b/05_OPERACIONES/backup-recovery.md index d21bddc..57f96e8 100644 --- a/05_OPERACIONES/backup-recovery.md +++ b/05_OPERACIONES/backup-recovery.md @@ -5,6 +5,15 @@ --- +## Principio Fundamental + +> **Cada instancia es responsable de su propio backup.** + +DECK y CORP son instancias autónomas. No dependen de ARCHITECT para hacer backups. +Cada servidor ejecuta su script de backup localmente y sube directamente a R2. + +--- + ## Estado Actual ### Backups Existentes @@ -20,94 +29,144 @@ --- -## Plan de Backup Propuesto +## Arquitectura de Backups -### PostgreSQL - Backup Diario - -```bash -#!/bin/bash -# /opt/scripts/backup_postgres.sh - -set -e - -DATE=$(date +%F) -BACKUP_DIR="/tmp/pg_backup" - -# Cargar credenciales R2 -source /home/orchestrator/orchestrator/.env -export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY" -export AWS_SECRET_ACCESS_KEY="$R2_SECRET_KEY" - -R2_ENDPOINT="https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com" - -mkdir -p $BACKUP_DIR - -# Backup ARCHITECT -echo "Backing up ARCHITECT..." -sudo -u postgres pg_dump architect | gzip > $BACKUP_DIR/architect_$DATE.sql.gz -aws s3 cp $BACKUP_DIR/architect_$DATE.sql.gz s3://architect/backups/postgres/ \ - --endpoint-url $R2_ENDPOINT - -# Cleanup local -rm -rf $BACKUP_DIR - -echo "Backup completado: $DATE" ``` - -### Cron Configuration - -```bash -# /etc/cron.d/tzzr-backup -# Backup diario a las 3:00 AM -0 3 * * * orchestrator /opt/scripts/backup_postgres.sh >> /var/log/tzzr-backup.log 2>&1 +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│ ARCHITECT │ │ DECK │ │ CORP │ +│ │ │ │ │ │ +│ backup.sh ───┼────►│ backup.sh ───┼────►│ backup.sh ───┼────► R2 +│ (local) │ │ (local) │ │ (local) │ +└──────────────┘ └──────────────┘ └──────────────┘ + │ │ + ▼ ▼ + Sin dependencia Sin dependencia + de ARCHITECT de ARCHITECT ``` --- -## Backup por Servidor +## Backup por Servidor (LOCAL) ### ARCHITECT (69.62.126.110) +**Ubicación script:** `/opt/scripts/backup_postgres.sh` + ```bash -# Base de datos: architect -sudo -u postgres pg_dump architect | gzip > architect_$(date +%F).sql.gz +#!/bin/bash +# Ejecutar EN ARCHITECT - backup local + +set -e +DATE=$(date +%F) + +# Credenciales R2 (desde Vaultwarden local o .env) +source /opt/architect/.env +export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY" +export AWS_SECRET_ACCESS_KEY="$R2_SECRET_KEY" +R2_ENDPOINT="https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com" + +# Backup local +sudo -u postgres pg_dump architect | gzip > /tmp/architect_$DATE.sql.gz # Subir a R2 -aws s3 cp architect_$(date +%F).sql.gz s3://architect/backups/postgres/ \ +aws s3 cp /tmp/architect_$DATE.sql.gz s3://architect/backups/postgres/ \ --endpoint-url $R2_ENDPOINT + +rm /tmp/architect_$DATE.sql.gz +echo "ARCHITECT backup completado: $DATE" ``` ### DECK (72.62.1.113) -```bash -# Base de datos: tzzr -ssh deck 'sudo -u postgres pg_dump tzzr | gzip' > deck_tzzr_$(date +%F).sql.gz +**Ubicación script:** `/opt/scripts/backup_postgres.sh` -# Subir a R2 -aws s3 cp deck_tzzr_$(date +%F).sql.gz s3://architect/backups/deck/ \ +```bash +#!/bin/bash +# Ejecutar EN DECK - backup local (NO depende de ARCHITECT) + +set -e +DATE=$(date +%F) + +# Credenciales R2 (desde Vaultwarden DECK) +source /opt/deck/.env +export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY" +export AWS_SECRET_ACCESS_KEY="$R2_SECRET_KEY" +R2_ENDPOINT="https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com" + +# Backup local +sudo -u postgres pg_dump tzzr | gzip > /tmp/deck_tzzr_$DATE.sql.gz + +# Subir a R2 (bucket propio de DECK) +aws s3 cp /tmp/deck_tzzr_$DATE.sql.gz s3://deck/backups/postgres/ \ --endpoint-url $R2_ENDPOINT + +rm /tmp/deck_tzzr_$DATE.sql.gz +echo "DECK backup completado: $DATE" ``` ### CORP (92.112.181.188) -```bash -# Base de datos: corp -ssh corp 'sudo -u postgres pg_dump corp | gzip' > corp_$(date +%F).sql.gz +**Ubicación script:** `/opt/scripts/backup_postgres.sh` -# Subir a R2 -aws s3 cp corp_$(date +%F).sql.gz s3://architect/backups/corp/ \ +```bash +#!/bin/bash +# Ejecutar EN CORP - backup local (NO depende de ARCHITECT) + +set -e +DATE=$(date +%F) + +# Credenciales R2 (desde Vaultwarden CORP) +source /opt/corp/.env +export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY" +export AWS_SECRET_ACCESS_KEY="$R2_SECRET_KEY" +R2_ENDPOINT="https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com" + +# Backup local +sudo -u postgres pg_dump corp | gzip > /tmp/corp_$DATE.sql.gz + +# Subir a R2 (bucket propio de CORP) +aws s3 cp /tmp/corp_$DATE.sql.gz s3://corp/backups/postgres/ \ --endpoint-url $R2_ENDPOINT + +rm /tmp/corp_$DATE.sql.gz +echo "CORP backup completado: $DATE" ``` ### HST (72.62.2.84) -```bash -# Base de datos: hst_images -ssh hst 'sudo -u postgres pg_dump hst_images | gzip' > hst_$(date +%F).sql.gz +**Ubicación script:** `/opt/scripts/backup_postgres.sh` -# Subir a R2 -aws s3 cp hst_$(date +%F).sql.gz s3://architect/backups/hst/ \ +```bash +#!/bin/bash +# Ejecutar EN HST - backup local + +set -e +DATE=$(date +%F) + +source /opt/hst/.env +export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY" +export AWS_SECRET_ACCESS_KEY="$R2_SECRET_KEY" +R2_ENDPOINT="https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com" + +sudo -u postgres pg_dump hst_images | gzip > /tmp/hst_$DATE.sql.gz + +aws s3 cp /tmp/hst_$DATE.sql.gz s3://hst/backups/postgres/ \ --endpoint-url $R2_ENDPOINT + +rm /tmp/hst_$DATE.sql.gz +echo "HST backup completado: $DATE" +``` + +--- + +## Cron en Cada Servidor + +Cada instancia configura su propio cron: + +```bash +# /etc/cron.d/tzzr-backup (en cada servidor) +# Backup diario a las 3:00 AM +0 3 * * * root /opt/scripts/backup_postgres.sh >> /var/log/backup.log 2>&1 ``` --- @@ -157,26 +216,30 @@ docker exec gitea rm /tmp/gitea-dump-$DATE.zip ## Estructura de Backups en R2 +Cada instancia usa su propio bucket: + ``` s3://architect/backups/ ├── postgres/ -│ ├── architect_2024-12-24.sql.gz -│ ├── architect_2024-12-23.sql.gz -│ └── ... -├── deck/ -│ ├── deck_tzzr_2024-12-24.sql.gz -│ └── ... -├── corp/ -│ ├── corp_2024-12-24.sql.gz -│ └── ... -├── hst/ -│ ├── hst_2024-12-24.sql.gz -│ └── ... +│ └── architect_2024-12-24.sql.gz └── gitea/ - ├── gitea-dump-2024-12-24_0300.zip - └── ... + └── gitea-dump-2024-12-24_0300.zip + +s3://deck/backups/ +└── postgres/ + └── deck_tzzr_2024-12-24.sql.gz + +s3://corp/backups/ +└── postgres/ + └── corp_2024-12-24.sql.gz + +s3://hst/backups/ +└── postgres/ + └── hst_2024-12-24.sql.gz ``` +> **Nota:** Cada instancia es dueña de sus backups. No hay dependencia cruzada. + --- ## Retención de Backups