Upload files to "/"

This commit is contained in:
davidtoribioeu 2026-03-14 19:33:39 +00:00
parent 85c6e357e9
commit 5cd0a16aeb
3 changed files with 1551 additions and 0 deletions

View file

@ -0,0 +1,575 @@
# Decision: Capa de observabilidad avanzada (punto 7)
## Contexto
Las Capas 1-6 proporcionan toda la telemetría: métricas (VictoriaMetrics), logs (Loki), seguridad (Wazuh), inventario (Netbox), alertas (Alertmanager → Telegram). La Capa 7 trata de qué hacemos con esos datos más allá de reaccionar a alertas: visibilidad por cliente, medición de niveles de servicio, planificación de capacidad, informes y correlación.
No introduce herramientas nuevas. Todo se construye sobre Grafana + VictoriaMetrics + Loki + Netbox ya desplegados.
5 subcapas:
- 7.1 Dashboards por cliente
- 7.2 SLOs/SLIs (niveles de servicio)
- 7.3 Capacity planning (planificación de capacidad)
- 7.4 Status page e informes para clientes
- 7.5 Correlación avanzada (métricas + logs + seguridad)
---
## 7.1 Dashboards por cliente
### El problema
Hoy para ver el estado de un cliente hay que:
1. Entrar en Grafana → buscar métricas del PVE donde están sus VMs
2. Entrar en PBS → buscar su datastore y ver si los backups están bien
3. Entrar en Wazuh → filtrar eventos por sus hosts
4. Entrar en Netbox → buscar qué tiene contratado
Para un técnico de soporte con un ticket abierto, esto son 4 herramientas y 5 minutos antes de saber qué pasa. Multiplicado por 50+ clientes.
### DECISION 7.1 (confirmada)
**Dashboard Grafana por cliente**: una vista única que muestra todo lo relevante de un cliente.
#### Contenido del dashboard
```
┌─────────────────────────────────────────────────────────┐
│ CLIENTE: ACME Corp [Último refresh: 2m] │
├─────────────────────────────────────────────────────────┤
│ │
│ 📊 RESUMEN │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ VMs: 5/5 UP │ │ Backups: OK │ │ Storage: 234/600│ │
│ │ │ │ Último: 3h │ │ GB (39%) │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
│ │
│ 🖥️ VMs │
│ ┌──────────┬───────┬─────────┬──────────┬───────────┐ │
│ │ VM │ CPU │ RAM │ Disco │ Estado │ │
│ ├──────────┼───────┼─────────┼──────────┼───────────┤ │
│ │ web-01 │ 12% │ 2.1/4GB │ 18/50GB │ ✅ UP │ │
│ │ db-01 │ 45% │ 7.2/8GB │ 42/100GB │ ✅ UP │ │
│ │ mail-01 │ 3% │ 1.1/2GB │ 8/20GB │ ✅ UP │ │
│ │ app-01 │ 28% │ 3.5/4GB │ 22/50GB │ ✅ UP │ │
│ │ gw-01 │ 1% │ 0.3/1GB │ 2/10GB │ ✅ UP │ │
│ └──────────┴───────┴─────────┴──────────┴───────────┘ │
│ │
│ 💾 BACKUPS (PBS1) │
│ ┌──────────┬──────────────┬────────┬────────────────┐ │
│ │ VM │ Último backup│ Tamaño │ Verify │ │
│ ├──────────┼──────────────┼────────┼────────────────┤ │
│ │ web-01 │ Hoy 03:15 │ 12 GB │ ✅ OK (hace 5d)│ │
│ │ db-01 │ Hoy 03:22 │ 38 GB │ ✅ OK (hace 3d)│ │
│ │ mail-01 │ Hoy 03:18 │ 6 GB │ ✅ OK (hace 7d)│ │
│ │ app-01 │ Hoy 03:20 │ 15 GB │ ✅ OK (hace 2d)│ │
│ │ gw-01 │ Hoy 03:16 │ 1 GB │ ✅ OK (hace 6d)│ │
│ └──────────┴──────────────┴────────┴────────────────┘ │
│ │
│ 📈 STORAGE PBS │
│ [███████████████░░░░░░░░░░░░░░░░░░░░░░░] 39% (234/600) │
│ Tendencia: +2.1 GB/semana → lleno en ~174 semanas │
│ │
│ 🔄 SYNC PBS2 (archivo) │
│ Última sincronización: Hoy 06:00 ✅ │
│ Snapshots en PBS2: 16 (7d + 4w + 5m) │
│ │
│ 🔒 SEGURIDAD (últimas 24h) │
│ Eventos Wazuh: 23 (todos nivel bajo) │
│ Alertas activas: 0 │
│ │
│ 🌐 CONECTIVIDAD │
│ WG Hub: ✅ conectado (handshake hace 47s) │
│ DNS: ✅ resolviendo │
│ Servicios publicados: portal.acme.com ✅ (200 OK) │
│ │
└─────────────────────────────────────────────────────────┘
```
#### Implementación técnica
El dashboard usa **variables de Grafana** para filtrar por cliente:
```
Variable: $customer
Type: Query
Data source: VictoriaMetrics
Query: label_values(pbs_datastore_size_bytes, datastore)
O bien: API de Netbox (plugin Grafana-Netbox)
```
Cada panel filtra por el cliente seleccionado:
```promql
# VMs del cliente (PVE exporter, filtrado por tags de Netbox)
pve_guest_info{name=~"$customer.*"}
# Storage PBS
pbs_datastore_used_bytes{datastore="$customer"}
pbs_datastore_size_bytes{datastore="$customer"}
# Último backup
pbs_snapshot_timestamp{datastore="$customer"}
# Eventos Wazuh (via Loki)
count_over_time({job="wazuh"} |= "$customer" [24h])
```
La relación VM↔cliente viene de Netbox (custom field `tenant`). El plugin `grafana-netbox-datasource` permite usar Netbox como data source de variables.
#### Un dashboard, todos los clientes
No se crea un dashboard por cliente. Es **un solo dashboard con variable dropdown**. El técnico selecciona "ACME" y ve todo de ACME. Selecciona "BETA" y ve todo de BETA.
Para clientes con acceso a Grafana (futuro): Grafana Organizations + RBAC limita cada cliente a ver solo sus datos.
#### Prioridad
| Paso | Qué | Cuándo |
|------|-----|--------|
| Construir dashboard base con paneles de VMs y backups | Mes 1 |
| Añadir storage PBS y tendencia | Mes 1 |
| Añadir sync PBS2 y verify | Mes 2 |
| Añadir seguridad (Wazuh) y conectividad (WG) | Mes 2-3 |
| Integrar variable de Netbox (automático al añadir clientes) | Mes 2 |
---
## 7.2 SLOs/SLIs (niveles de servicio medibles)
### El problema
Hoy se dice al cliente "tus backups se hacen diariamente" pero no se mide. Si un backup falla 3 días seguidos y nadie mira, no se sabe. Cuando el cliente pregunta "¿cuál ha sido mi uptime este mes?" la respuesta es "no sé, creo que bien".
Sin métricas de nivel de servicio:
- No puedes definir SLAs con datos reales
- No sabes si estás cumpliendo lo que prometes
- No puedes detectar degradación gradual (funciona, pero cada vez peor)
- No tienes datos para justificar precio o mejoras
### DECISION 7.2 (confirmada)
**Definir SLIs medibles y trackearlos en Grafana.** No es necesario implementar un sistema de SLO formal (Google SRE style con error budgets). Es suficiente con métricas que respondan a las preguntas clave del negocio.
#### SLIs definidos
| SLI | Qué mide | Cómo se calcula | Objetivo |
|-----|----------|----------------|----------|
| **Backup freshness** | ¿El backup es reciente? | Tiempo desde último backup exitoso | < 24h |
| **Backup success rate** | ¿Los backups funcionan? | Backups exitosos / backups programados (30 días) | > 99% |
| **Verify pass rate** | ¿Los backups son íntegros? | Verificaciones OK / verificaciones ejecutadas | > 99.5% |
| **Sync freshness** | ¿PBS2 está al día? | Tiempo desde última sincronización exitosa | < 48h |
| **Storage headroom** | ¿Queda espacio? | % libre del quota del cliente | > 15% |
| **VM availability** | ¿Las VMs están UP? | Tiempo UP / tiempo total (30 días) | > 99.5% |
| **Restore time** | ¿Cuánto tarda un restore? | Tiempo medio de restore (medido en ejercicios) | < 2h |
#### Implementación en Grafana
```promql
# SLI: Backup freshness (horas desde último backup)
(time() - pbs_snapshot_timestamp{datastore="$customer"}) / 3600
# SLI: Backup success rate (últimos 30 días)
# Requiere recording rule que cuente éxitos/intentos
pbs_backup_success_total{datastore="$customer"}
/ pbs_backup_attempts_total{datastore="$customer"}
# SLI: VM availability (30 días)
avg_over_time(up{job="pve", instance=~"$customer.*"}[30d])
# SLI: Storage headroom
1 - (pbs_datastore_used_bytes{datastore="$customer"}
/ pbs_datastore_size_bytes{datastore="$customer"})
```
#### Panel SLO en Grafana
```
┌──────────────────────────────────────────────────┐
│ SLOs - ACME Corp - Marzo 2026 │
├──────────────────────────────────────────────────┤
│ │
│ Backup Freshness ████████████████████ 100% │
│ Objetivo: < 24h Actual: 3h
│ │
│ Backup Success ████████████████████ 100% │
│ Objetivo: > 99% Actual: 30/30 días ✅ │
│ │
│ Verify Pass Rate ███████████████████░ 99.7% │
│ Objetivo: > 99.5% Actual: 1 warn en 30d ✅ │
│ │
│ Sync PBS2 ████████████████████ 100% │
│ Objetivo: < 48h Actual: 6h
│ │
│ Storage Headroom █████████████░░░░░░░ 61% │
│ Objetivo: > 15% Actual: 366 GB libre ✅ │
│ │
│ VM Availability ████████████████████ 99.97% │
│ Objetivo: > 99.5% Actual: 12min down ✅ │
│ │
│ Score global: 6/6 SLOs cumplidos ✅ │
│ │
└──────────────────────────────────────────────────┘
```
#### Alertas de SLO
| Alerta | Condición | Severidad |
|--------|-----------|-----------|
| SLOBackupFreshnessBreach | Backup > 24h para cualquier VM | Critical |
| SLOBackupSuccessLow | Success rate < 99% en ventana 7d | Warning |
| SLOSyncFreshnessBreach | Sync PBS2 > 48h | Critical |
| SLOStorageHeadroomLow | Storage headroom < 15% | Warning |
| SLOVMAvailabilityLow | VM availability < 99.5% en ventana 7d | Warning |
Estas alertas son **adicionales** a las de infraestructura (Capa 1). Las de Capa 1 dicen "algo falla ahora". Las de SLO dicen "estamos incumpliendo lo que prometimos".
#### Prioridad
| Paso | Qué | Cuándo |
|------|-----|--------|
| Definir SLIs de backup (freshness + success) | Mes 1 |
| Panel SLO básico en Grafana | Mes 2 |
| Añadir SLIs de sync, verify, storage | Mes 2 |
| Añadir SLI de VM availability | Mes 3 |
| Recording rules para cálculos eficientes | Mes 3 |
---
## 7.3 Capacity planning (planificación de capacidad)
### El problema
- Un cliente llena su quota de PBS un viernes a las 22h → no hay backups del fin de semana → ticket el lunes
- Un pool ZFS llega al 80% → rendimiento degrada → todos los clientes del pool sufren
- Se contratan 10 clientes nuevos y no se sabe si caben en el PBS actual o hay que provisionar otro
Hoy se reacciona cuando algo se llena. Con datos de tendencia se puede **anticipar semanas antes**.
### DECISION 7.3 (confirmada)
**Dashboards de tendencia en Grafana con funciones de predicción de VictoriaMetrics.**
VictoriaMetrics tiene funciones nativas de predicción que Prometheus no tiene:
#### Predicción de llenado
```promql
# ¿Cuándo se llena el datastore de ACME?
# predict_linear: regresión lineal sobre los últimos 30 días
predict_linear(pbs_datastore_used_bytes{datastore="acme"}[30d], 86400*90)
# ¿Cuántos días quedan para llegar al 100% del quota?
(pbs_datastore_size_bytes{datastore="$customer"} - pbs_datastore_used_bytes{datastore="$customer"})
/ deriv(pbs_datastore_used_bytes{datastore="$customer"}[30d])
/ 86400
```
#### Panel de capacity planning
```
┌──────────────────────────────────────────────────────────┐
│ CAPACITY PLANNING - Todos los clientes │
├──────────────────────────────────────────────────────────┤
│ │
│ ⚠️ ATENCIÓN REQUERIDA (se llenan en < 60 días)
│ ┌───────────┬──────────┬────────┬───────────────────┐ │
│ │ Cliente │ Usado │ Quota │ Días para llenarse│ │
│ ├───────────┼──────────┼────────┼───────────────────┤ │
│ │ DELTA │ 520/600 │ 87% │ ⚠️ 23 días │ │
│ │ GAMMA │ 380/500 │ 76% │ ⚠️ 45 días │ │
│ └───────────┴──────────┴────────┴───────────────────┘ │
│ │
│ ✅ SIN RIESGO (> 60 días) │
│ ┌───────────┬──────────┬────────┬───────────────────┐ │
│ │ ACME │ 234/600 │ 39% │ 174 días │ │
│ │ BETA │ 120/400 │ 30% │ 280 días │ │
│ │ ... (47 clientes más) │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ 📊 POOL ZFS GLOBAL │
│ pool9: 18.2 TB / 24 TB (76%) │
│ Tendencia: +120 GB/semana → lleno en ~48 semanas │
│ Recomendación: planificar ampliación antes del Q4 │
│ │
│ 📈 CRECIMIENTO POR CLIENTE (últimos 90 días) │
│ DELTA: +8.2 GB/semana (el que más crece) │
│ GAMMA: +5.1 GB/semana │
│ ACME: +2.1 GB/semana │
│ BETA: +1.3 GB/semana │
│ │
└──────────────────────────────────────────────────────────┘
```
#### Alertas de capacity
| Alerta | Condición | Severidad |
|--------|-----------|-----------|
| CapacityDatastoreFull30d | Datastore se llena en < 30 días (predicción) | Warning |
| CapacityDatastoreFull7d | Datastore se llena en < 7 días (predicción) | Critical |
| CapacityPoolFull90d | Pool ZFS se llena en < 90 días (predicción) | Warning |
| CapacityPoolFull30d | Pool ZFS se llena en < 30 días (predicción) | Critical |
Estas alertas permiten actuar **semanas antes**: contactar al cliente para ampliar quota, provisionar disco adicional, o redistribuir clientes entre pools.
#### Prioridad
| Paso | Qué | Cuándo |
|------|-----|--------|
| Panel básico de uso por cliente con tendencia | Mes 1-2 |
| Predicción de llenado (predict_linear) | Mes 2 |
| Alertas de capacity (30d, 7d) | Mes 2 |
| Panel de crecimiento por cliente | Mes 3 |
---
## 7.4 Status page e informes para clientes
### El problema
- El cliente no tiene visibilidad de su servicio: no sabe si sus backups funcionan, si su storage está bien, cuánto espacio le queda
- Cuando hay una incidencia, el cliente se entera porque algo no funciona, no porque se le haya comunicado
- No hay informes periódicos: "este mes todo fue bien" no tiene datos detrás
### DECISION 7.4 (confirmada)
**Dos herramientas, dos públicos, dos momentos:**
#### A) Status page per-client (tiempo real)
Cada cliente puede ver el estado actual de sus servicios. Dos opciones:
**Opción simple (mes 2): Grafana con permisos**
- Grafana Organizations: una org por cliente
- Dashboards de solo lectura con sus métricas
- SSO con Authentik (el cliente entra con su cuenta)
- Ve: VMs (UP/DOWN), backups (último, estado), storage (uso)
- No ve: métricas de otros clientes, infra interna
**Opción dedicada (mes 3+): página de diagnóstico custom**
Ya documentada en Capa 4.2: Flask/FastAPI ligero, SSO Authentik, detecta IP WG del cliente, muestra checks en tiempo real. Complementa el dashboard Grafana con tests activos (WG conectado, DNS resolviendo, certificado válido, PBS accesible).
#### B) Informes periódicos (mensuales)
Informe mensual generado automáticamente y enviado al cliente:
```
┌──────────────────────────────────────────────────┐
│ INFORME MENSUAL - ACME Corp - Marzo 2026 │
├──────────────────────────────────────────────────┤
│ │
│ RESUMEN EJECUTIVO │
│ ✅ Todos los SLOs cumplidos │
│ ✅ 0 incidencias de seguridad │
│ ✅ Storage en niveles saludables │
│ │
│ BACKUPS │
│ - Backups exitosos: 150/150 (100%) │
│ - Último verify: OK (12/03/2026) │
│ - Copia archivo (PBS2): sincronizada │
│ │
│ STORAGE │
│ - Uso actual: 234 GB / 600 GB (39%) │
│ - Crecimiento mes: +8.4 GB │
│ - Estimación llenado: 174 semanas │
│ │
│ DISPONIBILIDAD │
│ - Uptime VMs: 99.97% (12 min downtime) │
│ - Downtime planificado: 10 min (actualización) │
│ - Downtime no planificado: 2 min (reinicio red) │
│ │
│ SEGURIDAD │
│ - Eventos Wazuh: 687 (todos nivel informativo) │
│ - Alertas críticas: 0 │
│ - Vulnerabilidades parcheadas: 3 │
│ │
└──────────────────────────────────────────────────┘
```
Implementación:
```
Semaphore (cron mensual, día 1)
→ Playbook que consulta APIs:
- VictoriaMetrics (métricas del mes)
- Loki (eventos del mes)
- PBS API (backups, verify)
→ Genera PDF/HTML con template Jinja2
→ Envía por email o lo deja en Outline/Zammad
```
No es urgente. Es un diferenciador de servicio que se implementa cuando el stack está maduro.
#### Prioridad
| Paso | Qué | Cuándo |
|------|-----|--------|
| Grafana org por cliente (los que lo pidan) | Mes 3 |
| Página de diagnóstico custom | Mes 3+ |
| Template de informe mensual | Mes 4+ |
| Automatización de generación y envío | Mes 4+ |
---
## 7.5 Correlación avanzada (métricas + logs + seguridad)
### El problema
Las herramientas de las Capas 1-2 generan datos en silos:
- VictoriaMetrics tiene métricas (CPU, disco, red)
- Loki tiene logs (auth, syslog, PBS)
- Wazuh tiene eventos de seguridad (FIM, rootkits, vulnerabilidades)
Para investigar un incidente hay que saltar entre 3 herramientas y correlacionar mentalmente: "el disco subió a las 03:15, a ver qué hay en los logs a las 03:15, a ver si Wazuh detectó algo a las 03:15".
### DECISION 7.5 (confirmada)
**Grafana como panel de correlación único.** Grafana ya soporta múltiples data sources en el mismo dashboard y la misma vista temporal.
#### Dashboard de investigación
Un dashboard dedicado a investigar incidentes, con todos los data sources sincronizados en el mismo rango temporal:
```
┌─────────────────────────────────────────────────────────┐
│ INVESTIGACIÓN - Servidor: ns31787946 │
│ Rango temporal: [13/03/2026 02:00 - 04:00] │
├─────────────────────────────────────────────────────────┤
│ │
│ 📊 MÉTRICAS (VictoriaMetrics) │
│ CPU: ─────────────────╱╲───────────── pico 92% 03:12 │
│ IO: ────────────────╱──╲──────────── pico 03:12-03:18│
│ Disco:────────────────────/──────────── subió 2GB 03:15│
│ Red: ─────────────────────────────── normal │
│ │
│ 📝 LOGS (Loki) │
│ 03:10 [syslog] proxmox-backup: starting GC datastore X │
│ 03:12 [syslog] proxmox-backup: GC phase1 marking... │
│ 03:15 [syslog] zfs: pool9: io error on sda │
│ 03:15 [auth] sshd: Accepted key for root from 83.50… │
│ 03:16 [syslog] proxmox-backup: GC failed: IO error │
│ 03:18 [syslog] zfs: pool9: scrub repaired 4K │
│ │
│ 🔒 SEGURIDAD (Wazuh via Loki o API) │
│ 03:15 [level 7] File integrity: /var/log changed │
│ 03:15 [level 3] SSH login from known IP (informativo) │
│ │
│ CORRELACIÓN AUTOMÁTICA: │
│ → GC empezó a las 03:10 │
│ → Error de IO en disco sda a las 03:15 │
│ → GC falló por el error de IO │
│ → ZFS reparó el error (scrub) │
│ → El login SSH fue del técnico investigando │
│ → Conclusión: problema de disco, no seguridad │
│ │
└─────────────────────────────────────────────────────────┘
```
#### Cómo funciona en Grafana
Grafana tiene la funcionalidad **Explore** que permite:
- Seleccionar un rango temporal en una gráfica de métricas
- Ver automáticamente los logs de Loki del mismo período
- Usar **annotations** para marcar eventos de Wazuh en las gráficas de métricas
- **Split view**: métricas a la izquierda, logs a la derecha, sincronizados
```yaml
# Annotations automáticas en dashboards de métricas
# Marca eventos de Wazuh como líneas verticales en las gráficas
annotations:
- name: Wazuh Alerts
datasource: Loki
expr: '{job="wazuh"} |= "level" | json | level >= 10'
tagKeys: rule.description
textFormat: "{{rule.description}}"
```
#### Wazuh en Grafana
Dos opciones para tener datos de Wazuh en Grafana:
| Opción | Cómo | Pros | Contras |
|--------|------|------|---------|
| **Wazuh logs → Loki** | Alloy recoge logs de Wazuh Manager y los envía a Loki | Consultas LogQL en Grafana, mismo data source que otros logs | Requiere parsear formato Wazuh |
| **Wazuh API → Grafana** | Plugin Grafana o JSON datasource que consulta API de Wazuh | Datos estructurados, alertas con metadata | Plugin no oficial, mantenimiento |
**Recomendación**: Wazuh logs → Loki (opción A). Los alertas de Wazuh van al JSON log de `/var/ossec/logs/alerts/alerts.json`. Alloy los recoge y envía a Loki con labels (level, rule_id, agent_name). Consultas LogQL funcionan directamente.
#### Prioridad
| Paso | Qué | Cuándo |
|------|-----|--------|
| Wazuh alerts.json → Alloy → Loki | Mes 1 (junto con despliegue Alloy) |
| Dashboard de investigación básico (métricas + logs) | Mes 2 |
| Annotations de Wazuh en dashboards de métricas | Mes 2 |
| Dashboard de investigación completo con correlación | Mes 3 |
---
## Resumen Capa 7 completa (DECISIONES FINALES)
```
┌─────────────────────────────────────────────────────┐
│ CAPA 7: OBSERVABILIDAD AVANZADA │
├─────────────────────────────────────────────────────┤
│ │
│ 7.1 DASHBOARDS POR CLIENTE (confirmada) │
│ ┌───────────────────────────────────┐ │
│ │ Un dashboard Grafana con │ │
│ │ variable dropdown por cliente │ │
│ │ - VMs, backups, storage, sync │ │
│ │ - Seguridad, conectividad │ │
│ │ - Variables desde Netbox │ │
│ └───────────────────────────────────┘ │
│ │
│ 7.2 SLOs/SLIs (confirmada) │
│ ┌───────────────────────────────────┐ │
│ │ Métricas de nivel de servicio │ │
│ │ - Backup freshness < 24h
│ │ - Backup success > 99% │ │
│ │ - VM availability > 99.5% │ │
│ │ - Storage headroom > 15% │ │
│ │ - Sync freshness < 48h
│ │ Panel SLO en Grafana │ │
│ └───────────────────────────────────┘ │
│ │
│ 7.3 CAPACITY PLANNING (confirmada) │
│ ┌───────────────────────────────────┐ │
│ │ Predicción de llenado │ │
│ │ - predict_linear (VictoriaM.) │ │
│ │ - Alertas: lleno en <30d, <7d
│ │ - Crecimiento por cliente │ │
│ │ - Panel pool ZFS global │ │
│ └───────────────────────────────────┘ │
│ │
│ 7.4 STATUS PAGE + INFORMES (confirmada) │
│ ┌───────────────────────────────────┐ │
│ │ Grafana org per-client (mes 3) │ │
│ │ Página diagnóstico custom (3+) │ │
│ │ Informes mensuales auto (mes 4+)│ │
│ │ - Template Jinja2 → PDF/HTML │ │
│ │ - Envío automático por email │ │
│ └───────────────────────────────────┘ │
│ │
│ 7.5 CORRELACIÓN AVANZADA (confirmada) │
│ ┌───────────────────────────────────┐ │
│ │ Grafana como panel único de │ │
│ │ investigación │ │
│ │ - Métricas + Logs + Wazuh │ │
│ │ - Mismo rango temporal │ │
│ │ - Annotations de seguridad │ │
│ │ - Wazuh alerts → Loki │ │
│ └───────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
Recursos Capa 7:
- Herramientas nuevas: NINGUNA
- Todo se construye sobre Grafana + VictoriaMetrics +
Loki + Wazuh + Netbox (ya desplegados en Capas 1-2)
- Coste: 0 (dashboards, queries, recording rules)
- Esfuerzo: configuración progresiva meses 1-4
```

274
11-decision-ia-agentes.md Normal file
View file

@ -0,0 +1,274 @@
# Decision: IA y agentes para operaciones de infraestructura
## Contexto
Gestionamos 100-500 servidores PVE/PBS con un equipo tecnico reducido. Ya tenemos decidido: Ansible + Semaphore (automatizacion), n8n (orquestacion futura), Netbox (inventario), Zammad (tickets), VictoriaMetrics + Loki (metricas/logs), Wazuh (seguridad), Grafana (dashboards). La pregunta es: como integramos IA para que nos ayude operativamente.
Dos dimensiones: uso interactivo (tecnico + IA) y agentes automatizados (IA trabaja sola o semi-sola).
---
## 8.1 Claude Code interactivo: copiloto para tecnicos
### Que es
Claude Code es un CLI que se instala en una maquina Linux. El tecnico abre terminal, ejecuta `claude`, y trabaja de forma conversacional. Claude Code puede leer ficheros, ejecutar comandos, buscar en el codigo, y generar scripts/playbooks.
### Donde se instala
En la **VM Bastion** (ya existe, SSH jump host). El tecnico hace SSH al bastion y desde ahi usa Claude Code con acceso a:
- Repos Forgejo clonados (playbooks Ansible, scripts)
- CLI de PBS via SSH a los nodos (`proxmox-backup-manager`)
- CLI de ZFS via SSH
- Logs locales y remotos
- API de Netbox, PBS, PVE (curl)
### Casos de uso reales
| Escenario | Que hace el tecnico | Que hace Claude Code |
|-----------|--------------------|--------------------|
| GC lleva 3 dias | "revisa el GC del cliente ACME" | Lee logs, estado del job, uso de disco, diagnóstica |
| Cliente nuevo | "genera playbook para cliente X, 200GB, sync desde pbs3343" | Genera YAML validado siguiendo el patron existente |
| Alerta Wazuh | "analiza esta alerta de file integrity" | Lee evento, correlaciona con logs, valora si es falso positivo |
| Script heredado | "que hace status_disk.sh y como mejorarlo" | Lee, documenta, sugiere mejoras |
| Incidencia disco | "el pool9 del pbs tiene IO alto" | Revisa iostat, zpool status, encuentra el dataset problematico |
| Post-mortem | "genera el timeline del incidente de ayer" | Lee logs de Loki, Wazuh, metricas, construye cronologia |
### Implementacion
```bash
# En VM Bastion (Debian 12)
curl -fsSL https://claude.ai/install.sh | bash
# Configurar API key
export ANTHROPIC_API_KEY="sk-ant-..."
# Crear CLAUDE.md con contexto de la infra
cat > /root/CLAUDE.md << 'EOF'
# Infraestructura DoCloud
- Pool ZFS: pool9 (PBS), pool10 (PVE)
- Playbooks: /opt/ansible/
- Scripts legacy: /root/*.sh
- PBS API: https://localhost:8007
- Netbox API: https://netbox.internal/api/
- Clientes: ver `proxmox-backup-manager datastore list`
EOF
```
### Recursos
- CPU/RAM: despreciable (solo durante uso interactivo)
- Coste: API key Anthropic, ~$20-50/mes segun uso del equipo
- No requiere VM dedicada (va en Bastion existente)
### Seguridad
- El tecnico ya tiene acceso SSH al bastion con sus credenciales
- Claude Code hereda los permisos del usuario que lo ejecuta
- No abre puertos, no es un servicio, no tiene persistencia
- Logs de sesion almacenables para auditoria
---
## 8.2 Agentes automatizados via n8n + API Claude
### Arquitectura
Los agentes no son procesos permanentes. Son **workflows de n8n** que se disparan por un trigger (alerta, cron, webhook), enriquecen contexto consultando APIs, llaman a Claude API con un prompt especializado, y actuan sobre el resultado (crear ticket, generar informe, notificar).
```
Triggers Agentes (n8n workflows) Acciones
┌──────────────┐ ┌─────────────────────┐ ┌──────────────┐
│ Alertmanager ├──────────────►│ Triaje de alertas ├─────────►│ Ticket Zammad│
│ │ │ (prompt seguridad) │ │ │
├──────────────┤ ├─────────────────────┤ ├──────────────┤
│ Cron semanal ├──────────────►│ Capacity planning ├─────────►│ Informe │
│ │ │ (prompt storage) │ │ Outline │
├──────────────┤ ├─────────────────────┤ ├──────────────┤
│ Wazuh alert ├──────────────►│ Analisis seguridad ├─────────►│ Ticket Zammad│
│ (nivel ≥10) │ │ (prompt forense) │ │ + Mattermost │
├──────────────┤ ├─────────────────────┤ ├──────────────┤
│ Zammad ticket├──────────────►│ Provisioning assist ├─────────►│ MR en Forgejo│
│ (alta-client)│ │ (prompt ansible) │ │ │
└──────────────┘ └────────┬────────────┘ └──────────────┘
Consultas read-only
┌───────────┼───────────┐
│ │ │
VictoriaMetrics Loki Netbox
(metricas) (logs) (inventario)
```
### Agente 1: Triaje de alertas (mayor ROI)
- **Trigger**: Alertmanager envia webhook a n8n
- **Contexto que recopila**:
- Metricas del servidor afectado (VictoriaMetrics API, ultimas 2h)
- Logs recientes del servidor (Loki API, ultimos 30 min)
- Datos del servidor en Netbox (cliente, tipo, rol, SLA)
- Historial de alertas similares (VictoriaMetrics alerts API)
- **Prompt especializado**: incluye la definicion de severidades de la empresa, SLAs por cliente, y arboles de decision para problemas comunes (disco, CPU, backup fallido, conectividad)
- **Output**: Ticket en Zammad con: severidad calculada, diagnostico, acciones recomendadas, metricas relevantes embebidas
- **Ejemplo real**: Alerta "pbs_gc_duration_seconds > 86400 en ACME" → agente consulta tamaño datastore, snapshots, ultimo GC exitoso, y genera: "GC de ACME lleva 26h. Datastore: 1.2TB, 340 snapshots. Ultimo GC exitoso: hace 12 dias. Recomendacion: verificar si hay un sync job concurrente bloqueando. Si no, considerar maintenance-mode y GC forzado."
### Agente 2: Capacity planning (semanal)
- **Trigger**: Cron lunes 08:00
- **Contexto**: Uso de disco de todos los datastores (VictoriaMetrics), quotas ZFS, tendencias 30/60/90 dias
- **Output**: Informe en Outline con tabla priorizada:
```
| Cliente | Usado | Quota | Tendencia 30d | Dias hasta lleno | Accion |
|---------|-------|-------|---------------|------------------|--------|
| ACME | 82% | 600GB | +2.1%/semana | ~45 dias | Avisar |
| GAMMA | 91% | 300GB | +5.3%/semana | ~12 dias | URGENTE|
| BETA | 34% | 1TB | estable | >1 año | OK |
```
### Agente 3: Analisis de seguridad (evento Wazuh)
- **Trigger**: Wazuh alerta nivel ≥10 via webhook
- **Contexto**: Evento Wazuh completo, logs Loki del servidor (misma ventana), eventos correlacionados (mismo servidor, ultima hora), baseline de comportamiento normal del servidor
- **Output**: Ticket Zammad clasificado:
- **Falso positivo**: justificacion detallada de por que es benigno
- **Incidente real**: pasos de respuesta recomendados, basados en el playbook de incidentes (decision-incidentes.md)
- **Indeterminado**: que verificaciones adicionales hacer manualmente
### Agente 4: Asistente de provisioning
- **Trigger**: Ticket Zammad con tag "alta-cliente" o webhook ICSManager
- **Contexto**: Datos del cliente (nombre, GB, servidor sync), inventario Netbox (verificar duplicados), recursos disponibles en PVE destino
- **Output**: Branch en Forgejo con YAML del cliente listo para revisar, o ticket actualizado con datos validados para lanzar playbook desde Semaphore
### Implementacion en n8n
Cada agente es un workflow con estos nodos:
```
Webhook/Cron → HTTP Request(s) → Claude API → IF/Switch → Action(s)
(trigger) (recopilar (analizar) (decidir) (actuar)
contexto)
```
El nodo "Claude API" es un HTTP Request a `https://api.anthropic.com/v1/messages` con:
- System prompt: instrucciones especializadas del agente + contexto de la infra
- User message: datos recopilados en los pasos anteriores
- Modelo: `claude-sonnet-4-6` para agentes rutinarios (mas barato, suficiente), `claude-opus-4-6` para analisis de seguridad (maximo razonamiento)
### Coste estimado
| Agente | Frecuencia | Tokens/ejecucion | Modelo | Coste/mes |
|--------|-----------|-------------------|--------|-----------|
| Triaje alertas | ~50-100/dia | ~3000-5000 | Sonnet | $15-30 |
| Capacity planning | 1/semana | ~10000 | Sonnet | $1-2 |
| Seguridad Wazuh | ~5-20/dia | ~5000-8000 | Opus | $10-25 |
| Provisioning | ~5-10/mes | ~3000 | Sonnet | $1-2 |
| **Total** | | | | **~$30-60/mes** |
---
## 8.3 Evaluacion de OpenClaw
### Que es OpenClaw
OpenClaw (antes Clawdbot/Moltbot) es un agente de IA open-source autonomo creado por Peter Steinberger. Se ejecuta localmente, conecta a LLMs (Claude, GPT, DeepSeek), y usa plataformas de mensajeria (WhatsApp, Telegram, Slack, Discord) como interfaz. Tiene 145k+ estrellas en GitHub y ~400k usuarios.
Caracteristicas principales:
- Corre localmente, trae tu propia API key
- Multi-canal: WhatsApp, Telegram, Slack, Signal, Teams, Matrix
- 100+ AgentSkills precofiguradas (ejecutar shell, gestionar ficheros, web automation)
- Memoria persistente entre conversaciones
- Open source (MIT)
### Ventajas potenciales para nuestro caso
| Ventaja | Detalle |
|---------|---------|
| Multi-canal | Los tecnicos podrian interactuar via Telegram/Mattermost sin SSH |
| Open source | Sin vendor lock-in, personalizable |
| Skills extensibles | Podriamos crear skills para PBS, ZFS, Netbox |
| Self-hosted | Control total de datos |
### Problemas criticos para nuestro caso
#### 1. Seguridad: INACEPTABLE para infraestructura de produccion
Este es el punto definitivo. OpenClaw tiene vulnerabilidades documentadas graves:
- **Prompt injection via skills**: Cisco demostro que skills de terceros pueden hacer data exfiltration sin que el usuario lo note
- **ClawJacked (marzo 2026)**: Vulnerabilidad que permite a atacantes controlar el agente via WebSocket local y acceder a datos del dispositivo
- **Superficie de ataque amplia**: Un agente con acceso a shell en un servidor que gestiona 100-500 servidores de clientes es exactamente el vector de ataque que acabamos de sufrir con el backdoor PAM
**Nosotros acabamos de recuperarnos de un credential stealer que tenia acceso shell. Poner un agente de IA con acceso shell y vulnerabilidades conocidas de prompt injection seria repetir el mismo error.**
#### 2. Modelo de ejecucion inadecuado
OpenClaw es un **agente personal** (asistente general) ejecutandose como demonio. Nuestras necesidades son **agentes especializados** con scope limitado que se ejecutan solo cuando hay un trigger. Diferencia fundamental:
| Aspecto | OpenClaw | Nuestro modelo (n8n + API) |
|---------|----------|---------------------------|
| Ejecucion | Demonio permanente | Bajo demanda (trigger) |
| Permisos | Acceso amplio al sistema | Read-only a APIs especificas |
| Scope | General ("haz lo que te pida") | Especializado ("triaje de alertas") |
| Auditoria | Logs propios | Logs de n8n + Loki |
| Superficie de ataque | WebSocket + shell + mensajeria | Solo API HTTP saliente |
| Acciones | Ejecuta directamente | Genera recomendaciones, humano aprueba |
#### 3. Complejidad innecesaria
- OpenClaw requiere su propia infraestructura (MongoDB para memoria, gateway, canales)
- Nosotros ya tenemos n8n (orquestacion) + Zammad (interfaz humana) + Mattermost (chat futuro)
- Añadir OpenClaw duplica funcionalidad sin añadir valor
#### 4. Gobernanza incierta
- El creador (Peter Steinberger) se unio a OpenAI en febrero 2026
- Proyecto con hype extremo pero inmaduro en seguridad
- China ha restringido su uso en agencias gubernamentales por riesgos de seguridad
### Veredicto: NO usar OpenClaw
**OpenClaw no encaja en nuestro caso por razones de seguridad y arquitectura.** No necesitamos un agente general con acceso al sistema. Necesitamos agentes especializados, scoped, auditables, sin acceso directo a shell.
Nuestro stack ya cubre todo lo que OpenClaw ofrece de forma mas segura:
- **Chat con IA**: Claude Code interactivo en Bastion (controlado, sin demonio)
- **Automatizacion con IA**: n8n + Claude API (scoped, read-only, auditable)
- **Mensajeria del equipo**: Mattermost/Zammad (ya decidido)
- **Ejecucion de tareas**: Ansible + Semaphore (aprobacion humana)
Si en el futuro OpenClaw madura en seguridad y necesitamos un asistente conversacional para tecnicos via chat, se puede reevaluar. Pero hoy, con nuestro historial de seguridad, la respuesta es clara: **no**.
---
## 8.4 Orden de implementacion
| Fase | Que | Cuando | Dependencias |
|------|-----|--------|-------------|
| **Fase 0** | Claude Code en Bastion | Dia 1, tras desplegar Bastion | Solo API key Anthropic |
| **Fase 1** | Agente triaje de alertas | Mes 1-2 | n8n desplegado, Alertmanager configurado |
| **Fase 2** | Agente capacity planning | Mes 2-3 | VictoriaMetrics con historico ≥30 dias |
| **Fase 3** | Agente analisis seguridad | Mes 3-4 | Wazuh maduro, baseline establecida |
| **Fase 4** | Agente provisioning | Mes 4+ | Playbooks Ansible estables, Netbox poblado |
### Principios de diseño de los agentes
1. **Read-only por defecto**: Los agentes consultan APIs pero nunca ejecutan comandos en produccion
2. **Humano en el bucle**: Las acciones de escritura (tickets, MRs) son para que un humano revise y apruebe
3. **Scope minimo**: Cada agente tiene un prompt especializado y solo accede a las APIs que necesita
4. **Auditabilidad**: Todo queda en n8n (historial de ejecuciones) + Loki (logs)
5. **Coste controlado**: Sonnet para tareas rutinarias, Opus solo para analisis complejos
---
## Resumen
> **Capa 8: IA y agentes para operaciones**
>
> - **8.1**: Claude Code interactivo en VM Bastion (copiloto para tecnicos, dia 1)
> - **8.2**: Agentes automatizados via n8n + Claude API (4 agentes especializados, despliegue progresivo meses 1-4)
> - **8.3**: OpenClaw evaluado y **descartado** (riesgos de seguridad inaceptables, arquitectura inadecuada, funcionalidad cubierta por stack existente)
> - **8.4**: Orden de implementacion en 4 fases
>
> **Recursos adicionales**: ninguno (Claude Code en Bastion existente, agentes en n8n ya planificado)
> **Coste operativo**: ~$30-60/mes en API Anthropic
> **Herramientas nuevas**: ninguna (todo sobre stack ya decidido)

View file

@ -0,0 +1,702 @@
# Articulos de seguridad - Lecciones aprendidas de un incidente real
> Basado en el analisis forense de un servidor Proxmox Backup Server comprometido con un credential stealer via PAM, exfiltracion de contraseñas a un C2 externo, y persistencia mediante multiples artefactos en el sistema.
---
## Bloque 1: El incidente - Que paso y como se detecto
### 1. Como un backdoor PAM puede robar todas tus contraseñas SSH sin que lo notes
- No olvidar: explicar como `pam_exec.so` con `expose_authtok` permite capturar contraseñas en texto plano y enviarlas a un servidor externo con un simple curl. Mostrar el flujo completo: usuario hace login -> PAM ejecuta script -> contraseña capturada -> enviada por HTTP al atacante.
### 2. Anatomia de un credential stealer: del curl al C2 en 5 lineas de bash
- No olvidar: desglosar linea a linea el script `login.sh` real encontrado. Explicar el base64, el exfil via HTTP con `--max-time`, el `nohup` para no bloquear el login, y la descarga y ejecucion remota de comandos (`/run | bash`). Incluir el script completo como ejemplo.
### 3. Cronica de una intrusion: timeline de un servidor PBS comprometido
- No olvidar: reconstruir la linea temporal completa del ataque. Fecha de instalacion de los artefactos (9 de marzo), primera captura de credenciales, ficheros creados progresivamente (`ld.so.preload`, `login.sh`, `daemon`, `command-port`), y momento de deteccion (13 de marzo). Resaltar los 4 dias de ventana.
---
## Bloque 2: Vectores de ataque y persistencia
### 4. ld.so.preload: la linea mas peligrosa de tu sistema Linux
- No olvidar: explicar como un atacante puede inyectar librerias maliciosas en todos los procesos del sistema mediante este fichero. Diferencia entre un rootkit de userland y uno de kernel. Como monitorizar este fichero con auditd/inotify. Que aunque este vacio, su mera existencia reciente es un indicador de compromiso.
### 5. Ficheros fantasma en /usr/bin: como detectar binarios anomalos en directorios de sistema
- No olvidar: explicar la tecnica de buscar ficheros recientes en directorios de sistema (`find /usr/bin -mtime -7`). Cubrir los distintos artefactos encontrados: ficheros de 0 bytes como marcadores (`daemon`), scripts maliciosos con nombres inocuos (`login.sh`), directorios de configuracion del malware (`/usr/local/sbin/env/`). Un binario legitimo en /usr/bin rara vez cambia fuera de actualizaciones de paquetes.
### 6. Persistencia sin cron ni systemd: tecnicas de backdoor via PAM
- No olvidar: explicar por que PAM es un vector de persistencia tan efectivo: se ejecuta en cada autenticacion, no aparece en `crontab -l`, no crea servicios visibles, y es transparente para el usuario. Comparar con otros metodos de persistencia (cron, systemd timers, rc.local, authorized_keys) y por que PAM es mas sigiloso.
### 7. El fichero de 27 bytes que anulo toda tu seguridad SSH: cloud-init y sshd_config.d
- No olvidar: mostrar como `sshd_config.d/50-cloud-init.conf` con `PasswordAuthentication yes` sobreescribe silenciosamente el `PasswordAuthentication no` del config principal. Explicar el orden de precedencia de `Include` en sshd. Recalcar que despues de cada despliegue hay que auditar los drop-ins.
### 8. Cuando el atacante ya tiene tu contraseña: por que cambiarla ANTES de limpiar
- No olvidar: recalcar que las credenciales ya estan en manos del atacante desde el momento de la captura. Limpiar el backdoor sin rotar credenciales deja la puerta abierta. Incluir checklist de rotacion: contraseña root, usuarios PBS, API tokens, claves SSH del servidor.
---
## Bloque 3: Deteccion y respuesta
### 9. Checklist forense rapido: como saber si tu servidor Linux esta comprometido en 10 minutos
- No olvidar: incluir la checklist completa usada en esta investigacion, en orden de prioridad:
1. `grep pam_exec /etc/pam.d/*`
2. `cat /etc/ld.so.preload`
3. `find /usr/bin /usr/sbin -mtime -30`
4. `awk -F: '$3==0' /etc/passwd`
5. `cat /root/.ssh/authorized_keys`
6. `crontab -l` y `/etc/cron.d/`
7. `ss -tulnp` y `ss -tnp state established`
8. `ls -la /tmp /dev/shm`
9. `ps auxf` comparado con `/proc/[0-9]*`
10. `systemctl list-unit-files --state=enabled`
### 10. Auditoria post-incidente en Proxmox: del host a las VMs
- No olvidar: explicar como extender la investigacion del host a las VMs usando `qm guest exec`. Mostrar que el guest agent de QEMU permite ejecutar comandos de auditoria dentro de las VMs sin necesidad de SSH. Verificar que la infeccion no se propago lateralmente.
### 11. Señales de alerta que no debes ignorar: IOCs de un credential stealer
- No olvidar: listar los indicadores de compromiso (IOCs) concretos encontrados: fichero `ssh_auth.log` con credenciales en base64, conexiones salientes a IPs no esperadas en puertos altos (10480), ficheros recientes en `/usr/bin` que no corresponden a ningun paquete (`dpkg -S`), directorio `env` dentro de `/usr/local/sbin/`.
### 12. Como usar dpkg --verify para detectar binarios del sistema modificados
- No olvidar: explicar que `dpkg --verify` compara los ficheros instalados con los checksums del paquete original. Si un binario de sistema fue reemplazado por el atacante, aparecera como modificado. Limitaciones: no detecta ficheros nuevos añadidos, solo modificaciones a ficheros existentes.
---
## Bloque 4: Prevencion y hardening
### 13. Firewall estricto pero comprometido: cuando la amenaza ya esta dentro
- No olvidar: mostrar que este servidor tenia un firewall bien configurado (SSH limitado por IP, politica DROP, bloqueo de puertos de mineria) y aun asi fue comprometido. El firewall perimetral no protege contra amenazas que ya lograron acceso. Capas adicionales necesarias: auditd, file integrity monitoring, deteccion de anomalias.
### 14. Hardening SSH mas alla de cambiar el puerto: guia completa para Proxmox
- No olvidar: cubrir todos los aspectos: deshabilitar password auth (y verificar que cloud-init no lo reactive), usar solo claves SSH, configurar `AllowUsers`/`AllowGroups`, limitar por IP en firewall Y en sshd_config, habilitar fail2ban, configurar auditd para cambios en sshd_config y PAM.
### 15. Monitorizar /etc/pam.d con auditd: detectar manipulaciones antes de que sea tarde
- No olvidar: proporcionar reglas de auditd concretas para vigilar cambios en `/etc/pam.d/`, `/etc/ld.so.preload`, `/usr/bin/`, `/usr/sbin/`. Incluir configuracion de alertas y como integrar con un SIEM o envio de correo.
### 16. Bloqueo de C2 y mineria: reglas de salida que todo servidor deberia tener
- No olvidar: documentar el patron de reglas OUT DROP por puertos de stratum (3333, 5555, 7777, 14433, 14444) y por IPsets de pools/C2. Explicar como añadir nuevos IOCs al firewall de Proxmox. Recalcar la importancia de politica `policy_out: DROP` con whitelist explicita.
### 17. Segmentacion de backups: por que tu PBS no deberia tener acceso general a internet
- No olvidar: un servidor de backups solo necesita trafico entrante de los clientes de backup y salida para DNS, NTP y repositorios de actualizaciones. Cualquier otra conexion saliente es sospechosa. Diseñar reglas de salida minimas para un PBS.
---
## Bloque 5: Infraestructura y operaciones
### 18. Tu servidor DNS esta caido y no lo sabes: monitorizacion de servicios criticos en Docker
- No olvidar: el caso real de disco lleno al 100% en la VM del DNS que tumbo PowerDNS sin que nadie se enterase. Configurar alertas de espacio en disco, healthchecks funcionales (el healthcheck de este PowerDNS usaba `pdns_control ping` que no funcionaba), y monitorizacion externa de resolucion DNS.
### 19. Healthchecks de Docker que mienten: cuando "unhealthy" no significa lo que crees
- No olvidar: el caso concreto donde `pdns_control ping` devolvia "Unknown command: PING" pero el servicio DNS funcionaba perfectamente. Diferencia entre healthcheck del contenedor y salud real del servicio. Como diseñar healthchecks que realmente validen la funcionalidad.
### 20. Gestion de espacio en disco para VMs con Docker: lecciones de un DNS caido
- No olvidar: calcular correctamente el espacio necesario para imagenes Docker, volumenes de datos (MariaDB), logs y espacio temporal. La VM tenia 13GB para un stack completo de DNS con base de datos. Alertas proactivas antes de llegar al 100%.
### 21. PowerDNS como secundario: errores comunes en la sincronizacion de zonas
- No olvidar: explicar los errores de SOA "Query Refused" encontrados en 3 dominios (actioestudio.com, leristextil.com, oxigendc.com). Causas comunes: ACLs en el primario, dominios eliminados sin limpiar el secundario, problemas de red. Como monitorizar la sincronizacion de zonas.
---
## Bloque 6: Cultura y procesos
### 22. Respuesta a incidentes sin panico: guia paso a paso para sysadmins
- No olvidar: documentar el proceso seguido en este incidente como ejemplo: primero investigar sin tocar nada, recopilar evidencias, identificar el alcance (host + VMs), verificar propagacion lateral, limpiar, y rotar credenciales. Enfatizar que no se debe apagar ni reinstalar antes de recopilar evidencias.
### 23. El factor tiempo: 4 dias con un backdoor activo y que hacer para reducir la ventana
- No olvidar: desde la instalacion del backdoor (9 marzo) hasta la deteccion (13 marzo) pasaron 4 dias. Cada login en ese periodo fue capturado. Herramientas y practicas para reducir el tiempo de deteccion: file integrity monitoring, auditd, revision periodica de logs, honeypots internos.
### 24. Documentar para sobrevivir: como un CLAUDE.md bien hecho acelero la respuesta al incidente
- No olvidar: el fichero CLAUDE.md del servidor contenia toda la arquitectura, comandos, y configuracion documentada, lo que permitio una investigacion rapida y contextualizada. Argumentar a favor de mantener documentacion operativa actualizada como herramienta de seguridad.
### 25. Post-mortem sin culpables: como convertir un incidente de seguridad en mejora continua
- No olvidar: estructura de un post-mortem efectivo: que paso, timeline, como se detecto, como se resolvio, que salio bien, que salio mal, acciones correctivas con responsable y fecha. El objetivo es mejorar procesos, no buscar culpables.
---
## Bloque 7: Investigacion forense avanzada
### 26. Forense en caliente vs en frio: cuando NO apagar el servidor comprometido
- No olvidar: en este caso la investigacion se hizo con el sistema en ejecucion, lo que permitio ver conexiones activas, procesos en memoria y ficheros abiertos. Si se hubiera apagado, se habria perdido evidencia volatil. Explicar cuando si conviene apagar (ransomware activo, exfiltracion masiva en curso) y cuando no.
### 27. El arte de leer /proc: detectar procesos ocultos y binarios eliminados
- No olvidar: la tecnica de comparar el conteo de `ps aux` con `ls /proc/[0-9]*` para detectar procesos ocultos. Buscar `/proc/*/exe` con "(deleted)" para encontrar malware que se borro del disco pero sigue ejecutandose en memoria. En este caso salio limpio, pero explicar que habria significado si no.
### 28. Reconstruir la actividad del atacante a traves de timestamps de ficheros
- No olvidar: usar `stat` para ver Birth/Modify/Change/Access de los artefactos. En este incidente los timestamps revelaron el orden de instalacion: primero `command-port` y `ld.so.preload` (9 mar 18:58), luego `login.sh` (9 mar 19:00), luego `daemon` (13 mar 08:55). Explicar MAC times y como interpretarlos.
### 29. Buscar al atacante: OSINT basico sobre IPs de C2 y como reportar
- No olvidar: que hacer con la IP del C2 (91.208.162.132): whois, geolocalizar, comprobar en bases de datos de amenazas (AbuseIPDB, VirusTotal, Shodan), reportar al ISP/CERT. Explicar que el puerto 10480 y el path `/run` son firma del malware que pueden usarse para buscar variantes.
### 30. Analisis de trafico de red post-incidente: que buscar en los logs del firewall
- No olvidar: revisar los logs de salida del firewall de Proxmox (log_level_out: info) para encontrar conexiones al C2 que pasaron desapercibidas. Buscar patrones: conexiones a puertos altos, transferencias pequeñas periodicas (beaconing), conexiones desde procesos inesperados.
---
## Bloque 8: Seguridad en entornos de backup
### 31. Tu servidor de backups es el objetivo mas valioso: por que los atacantes lo buscan primero
- No olvidar: un PBS comprometido da acceso a los backups de TODOS los clientes. El atacante puede robar datos historicos, inyectar ransomware en los backups, o destruirlos. Explicar por que el servidor de backup necesita el maximo nivel de hardening.
### 32. El modelo de multiplicador 6x en PBS: cuando las quotas ZFS te salvan de un desastre
- No olvidar: explicar el modelo de provisionamiento encontrado (commercial x6 quota, x5 reservation) y como las quotas ZFS limitan el impacto si un atacante intenta llenar el almacenamiento. Sin quotas, un solo datastore comprometido podria consumir todo pool9.
### 33. Aislamiento de datastores en PBS: un cliente comprometido no debe afectar a otros
- No olvidar: cada cliente tiene su propio usuario PBS con permisos DatastorePowerUser limitados a su datastore. Revisar que las ACLs estan bien configuradas. Un atacante con credenciales de un cliente no deberia poder acceder a otros datastores.
### 34. Verificacion y garbage collection: mantenimiento de PBS como herramienta de seguridad
- No olvidar: los verify jobs detectan backups corruptos que podrian indicar manipulacion. El GC recurrente libera espacio y elimina chunks huerfanos. Sin mantenimiento, un backup comprometido podria pasar desapercibido meses. Relacionar con los cron jobs encontrados en el servidor.
### 35. Sync jobs y la cadena de confianza: cuando sincronizas malware sin saberlo
- No olvidar: los sync jobs copian backups de servidores remotos. Si el servidor origen esta comprometido, los backups sincronizados pueden contener malware. Explicar como validar la integridad post-sync y la importancia de verificar los origenes.
---
## Bloque 9: Docker y contenedores en produccion
### 36. Docker en produccion sin monitoring es como conducir sin retrovisores
- No olvidar: el stack de DNS completo (PowerDNS + MariaDB + Traefik + admin panels) estaba caido sin alertas. Herramientas de monitoring para Docker: Uptime Kuma, Prometheus + cAdvisor, Watchtower para actualizaciones, y alertas por correo/Telegram.
### 37. Dimensionar discos para VMs con Docker: la regla del triple
- No olvidar: calcular espacio real necesario: imagenes base + capas overlay + volumenes de datos + logs + espacio temporal de Docker + margen del 30%. En este caso 13GB era insuficiente para el stack, 23GB resolvio el problema pero deberia planificarse desde el inicio.
### 38. Traefik como puerta de entrada: hardening del reverse proxy en tu stack Docker
- No olvidar: el stack usaba Traefik con Let's Encrypt para multiples servicios (admin DNS, phpMyAdmin, dashboard). Revisar que los paneles de administracion tengan autenticacion, que los certificados se renueven, y que las cabeceras de seguridad esten configuradas.
### 39. Secretos en docker-compose.yml: el peligro de las contraseñas en texto plano
- No olvidar: en los compose encontrados habia contraseñas en claro (`MYSQL_ROOT_PASSWORD`, `PDNS_API_KEY=secret`, etc.). Alternativas: Docker secrets, ficheros .env con permisos restrictivos, HashiCorp Vault. Nunca commitear contraseñas en repositorios.
---
## Bloque 10: Automatizacion y herramientas
### 40. Construir tu propio scanner de rootkits con bash en 100 lineas
- No olvidar: basandose en los comandos usados en esta investigacion, crear un script que automatice la deteccion de: PAM modifications, ld.so.preload, ficheros recientes en /usr/bin, usuarios UID 0 extra, authorized_keys sospechosas, conexiones a IPs externas, procesos ocultos. Publicar en GitHub.
### 41. Usar qm guest exec para auditar todas tus VMs desde el host Proxmox
- No olvidar: script que itere sobre todas las VMs con guest agent activo y ejecute el checklist de seguridad. Generar un informe por VM. Requisitos: guest agent instalado y corriendo, VMs encendidas. Limitaciones de timeout y tamaño de output.
### 42. Alertas automaticas de cambios en ficheros criticos con inotifywait
- No olvidar: configurar inotifywait para vigilar en tiempo real cambios en `/etc/pam.d/`, `/etc/ssh/sshd_config*`, `/etc/ld.so.preload`, `/usr/bin/`, `/usr/sbin/`. Enviar alerta inmediata por correo o webhook. Mas ligero que auditd para servidores pequeños.
### 43. Integrar la seguridad en tus scripts de provisionamiento: lecciones de modificar.sh
- No olvidar: el script `modificar.sh` crea datastores, usuarios y sync jobs. Deberia tambien verificar la integridad del sistema antes de operar, comprobar que PAM no esta modificado, y registrar un hash de los ficheros criticos tras cada cambio. Seguridad como parte del workflow, no como algo separado.
---
## Bloque 11: Monitoring e inventario - Decisiones de arquitectura
### 44. Por que Netbox y no GLPI: elegir CMDB para infraestructura Proxmox
- No olvidar: comparar ambas herramientas en el contexto real de gestionar 100-500 PBS/PVE. Netbox gana en IPAM, modelo de tenants/clientes, integracion nativa con Ansible y Prometheus. GLPI gana en autodiscovery con agente y ticketing integrado. Para un modelo de negocio donde ICSManager alimenta el inventario via API, Netbox es la eleccion porque su API REST es superior.
### 45. Inventario que se rellena solo: como ICSManager alimenta Netbox en el proceso comercial
- No olvidar: el flujo cliente pide recursos -> ICSManager procesa -> Netbox recibe via API -> Ansible provisiona -> Prometheus monitoriza. El inventario se genera como subproducto del proceso de venta, no como tarea manual. Incluir los custom fields especificos para PBS: commercial_size_gb, quota_gb, reservation_gb, sync_server, pbs_status. Reconciliacion con la API de Proxmox para detectar recursos no inventariados.
### 46. Checkmk nos arruino el rendimiento: lecciones de elegir herramientas de monitoring
- No olvidar: la experiencia real con Checkmk (version opensource con Nagios por debajo, consumo desmesurado de recursos). Criterios para evaluar herramientas de monitoring antes de comprometerse: consumo de recursos por agente/target, escalabilidad real probada, ecosistema de integraciones, curva de aprendizaje, coste oculto de la version enterprise. No fiarse de demos con 10 servidores cuando vas a tener 500.
### 47. VictoriaMetrics vs Prometheus: por que elegimos Victoria para 500 servidores
- No olvidar: comparativa detallada de consumo de RAM (5-10x menos), disco (7-10x menos con compresion), retencion nativa sin Thanos/Cortex, compatibilidad 100% con PromQL y todos los exporters. A 100+ servidores un Prometheus single empieza a sufrir. VictoriaMetrics single-node gestiona miles de targets sin despeinarse. MetricsQL es superset de PromQL (compatible hacia atras).
### 48. El stack de monitoring que realmente necesitas: VictoriaMetrics + Grafana + vmagent
- No olvidar: arquitectura completa con diagrama de 4 capas (exporters -> vmagent -> VictoriaMetrics -> Grafana). Explicar cada componente y por que existe. node_exporter en todos los servidores (5MB RAM), pve_exporter por cluster, pbs-exporter centralizado en multi-target. Dimensionamiento: VM de 4 vCPU, 8GB RAM, 200GB disco para 500 servidores con retencion de 1 año.
### 49. Uptime Kuma no es monitoring: donde encaja el check binario en tu stack
- No olvidar: Uptime Kuma es complementario, no sustituto. Es "vivo o muerto", no metricas. Usarlo para: checks externos de disponibilidad (PBS:8007, DNS:53, paneles web), certificados SSL a punto de expirar, pagina de status para clientes. NO usarlo para: metricas de rendimiento, alertas de disco/ZFS, estado de jobs. Evitar la trampa de pensar que con Kuma ya tienes monitoring.
### 50. pbs-exporter de natrontech: monitoring de PBS sin reinventar la rueda
- No olvidar: el exporter comunitario cubre datastores, snapshots por VM, ultimo backup por VM, host metrics, suscripcion. Modo multi-target: una instancia para N servidores PBS. Complementar con script de 40 lineas para GC/verify/sync jobs via textfile collector. Configuracion completa: usuario monitoring@pbs con Audit, API token, despliegue Docker o systemd.
### 51. Las 10 alertas que habrian evitado este desastre
- No olvidar: alertas concretas en PromQL que, de haber estado configuradas, habrian detectado los problemas encontrados:
1. Disco > 80% (habria alertado del DNS caido por disco lleno)
2. ZFS pool no ONLINE
3. PBS sin backup > 48h por datastore
4. GC no ejecutado en 3 dias
5. Verify con errores
6. Sync fallido
7. Cambio en ficheros PAM (seguridad)
8. Nuevo fichero en /usr/bin (seguridad)
9. Conexion saliente a IP no whitelisted
10. Certificado SSL expira en < 14 dias
### 52. Dashboard de capacity planning: predecir cuando se llena tu pool ZFS
- No olvidar: usar `predict_linear()` de PromQL para proyectar crecimiento. Dashboard con tendencia 12 meses, prediccion de llenado por pool y por datastore, deteccion de clientes con quotas sobredimensionadas (oportunidad de reclamar espacio), y resumen comercial (GB vendidos vs GB reales usados vs quota asignada con ratio 6x).
### 53. Tres dashboards de Grafana que todo equipo PBS necesita
- No olvidar: diseño concreto de cada dashboard con mockups ASCII:
1. **NOC/pantalla grande**: estado global, datastores con problemas, jobs del dia
2. **Operaciones por datastore**: espacio, quota, dedup ratio, estado de cada job, snapshots recientes
3. **Management/capacity**: tendencias, prediccion, oportunidades de optimizacion, resumen comercial
---
## Bloque 12: Tecnicas de respuesta y contencion
### 54. chattr +i como trampa: usar ficheros inmutables para bloquear la reinstalacion de malware
- No olvidar: la tecnica real usada por el equipo en este incidente. Crear `/usr/bin/daemon` vacio con `chattr +i` (inmutable) para que el malware no pueda recrear el binario. El fichero actua como trampa: si alguien intenta escribirlo, falla, y si se intenta borrar, tambien falla. Util como medida de contencion mientras se investiga. Limitaciones: el atacante con root puede hacer `chattr -i`.
### 55. Verificar la limpieza: checklist post-remediacion para confirmar que no queda nada
- No olvidar: el proceso completo de re-auditoria tras la limpieza. No basta con borrar los ficheros conocidos: hay que reverificar PAM, SSH config, authorized_keys, crontabs, systemd units, procesos, conexiones, kernel modules. Comparar con la auditoria original. Incluir la tabla de estado (eliminado/limpio/pendiente) usada en este incidente.
### 56. Cuando dpkg --verify te miente: falsos positivos y como interpretarlos
- No olvidar: en este incidente, `/usr/bin/gzip` aparecia como modificado en `dpkg --verify`. La investigacion revelo que era un wrapper legitimo hacia `pigz` (compresion paralela). Explicar como distinguir modificaciones maliciosas de personalizaciones legitimas: revisar el contenido, comprobar timestamps, verificar si hay razon operativa. No entrar en panico, investigar.
### 57. El PBS:8007 abierto al mundo: cuando un puerto de backup se convierte en superficie de ataque
- No olvidar: en el firewall del servidor, el puerto 8007 de PBS estaba abierto a todas las IPs (`IN ACCEPT -p tcp -dport 8007`) para recibir backups de clientes. Esto expone la API de PBS a internet. Aunque requiere autenticacion, es un vector para fuerza bruta, CVEs futuros, o credenciales robadas (como en este caso). Alternativa: VPN o whitelist de IPs de clientes.
---
## Bloque 13: Gestion de DNS e infraestructura auxiliar
### 58. Tu servidor DNS es una VM de 13GB: dimensionamiento real de servicios criticos
- No olvidar: la VM del DNS (ns1.docloud.com) tenia 13GB de disco para un stack Docker completo (PowerDNS + MariaDB + Traefik + phpMyAdmin + admin panels + Homepage). Se lleno al 100% y todo cayo. Regla practica para Docker: imagenes + datos + logs + overlay + 30% margen. Para un stack de DNS con BBDD: minimo 25-30GB. Alertar al 80%.
### 59. PowerDNS en Docker: arquitectura de un DNS autoritativo secundario
- No olvidar: documentar la arquitectura real encontrada: MariaDB como backend, PowerDNS auth como secundario sincronizando zonas desde primario (51.254.111.145), Traefik como reverse proxy para paneles admin con Let's Encrypt, PowerDNS Admin para gestion web. Red Docker `pdns_network` compartida. Lecciones: separar datos (volumenes) de servicios, no exponer phpMyAdmin sin autenticacion fuerte.
### 60. Investigar dentro de VMs sin SSH: qm guest exec como herramienta forense
- No olvidar: en este incidente se uso `qm guest exec` para auditar la VM del DNS sin necesidad de SSH (que podria estar comprometido). El guest agent de QEMU permite ejecutar comandos arbitrarios dentro de la VM desde el host. Requisitos: qemu-guest-agent instalado y corriendo, VM encendida. Limitaciones: timeout de comandos, tamaño de output, no interactivo. Ideal para: verificar infeccion, comprobar servicios, diagnosticar problemas de disco.
---
## Bloque 14: De scripts artesanales a infraestructura como codigo
### 61. De modificar.sh a Ansible: evolucion natural de la automatizacion en PBS
- No olvidar: el script `modificar.sh` encontrado hace todo lo necesario (ZFS, datastore, usuario, password, ACL, sync job, verify job) pero es un script bash monolitico en /root. A 100+ servidores, esto deberia ser un playbook Ansible idempotente versionado en git. Mostrar la transformacion paso a paso, manteniendo la logica de negocio (multiplicador 6x, scheduling aleatorio de sync).
### 62. El peligro de los scripts en /root: por que versionar tu automatizacion
- No olvidar: todos los scripts operativos (modificar.sh, lista.sh, gc_jobs.sh, verify_jobs.sh, status_disk.sh) estaban en /root sin control de versiones. Si el servidor se pierde, se pierde toda la operativa. Si un tecnico modifica un script y rompe algo, no hay rollback. Solucion: Gitea/Forgejo + Ansible + CI/CD. El coste de no versionar es mayor que el de configurar git.
### 63. Netbox como fuente de verdad para Ansible: inventario dinamico para PBS
- No olvidar: con el plugin `netbox.netbox.nb_inventory`, Ansible genera su inventario directamente desde Netbox. Cuando ICSManager crea un cliente en Netbox, Ansible lo ve automaticamente en el proximo run. Custom fields de Netbox (quota, sync_server, pve_host) se convierten en variables de Ansible. Elimina ficheros de inventario manuales y el riesgo de desincronizacion.
---
## Bloque 15: Logs centralizados - Decisiones de arquitectura
### 64. Tus logs locales no valen nada si el atacante tiene root
- No olvidar: en este incidente, el backdoor escribia credenciales robadas en `/var/log/ssh_auth.log`. Ese fichero estaba solo en el servidor comprometido. Si el atacante lo hubiera borrado (trivial con root), no habria quedado evidencia. Los logs deben salir del servidor en tiempo real a un destino que el atacante no controle. Esta es la razon numero uno para centralizar logs.
### 65. Grafana Loki vs Graylog vs ELK: por que elegimos Loki para 500 servidores
- No olvidar: la decision se basa en que ya tenemos Grafana y VictoriaMetrics. Loki se integra nativamente en el mismo panel. Graylog requiere Elasticsearch + MongoDB (7GB RAM minimo) y es otra UI separada. ELK necesita 16GB+ de RAM y es matar moscas a cañonazos a esta escala. Loki no indexa contenido (solo labels), lo que lo hace 5-10x mas ligero. LogQL es similar a PromQL, misma curva de aprendizaje.
### 66. Grafana Alloy: un solo agente para logs y metricas en cada servidor
- No olvidar: Alloy reemplaza a Promtail (solo logs) y puede reemplazar tambien a node_exporter y vmagent. Un unico agente que consume 30-50MB de RAM por servidor. Comparar con Checkmk agent (200-500MB). Configuracion en formato River. Estrategia: empezar con Alloy solo para logs, expandir a metricas cuando el equipo este comodo.
### 67. Que logs centralizar primero: la piramide de prioridades
- No olvidar: no centralizar todo el dia 1. Prioridad 1 (dia 1): auth.log y syslog (seguridad basica). Prioridad 2 (semana 1): firewall PVE, PBS logs, dpkg.log. Prioridad 3 (mes 1): Docker logs de VMs, cron logs, Proxmox cluster logs. Empezar con lo que habria detectado el incidente y expandir.
### 68. LogQL para sysadmins: las 10 consultas que usaras todos los dias
- No olvidar: consultas practicas reales:
1. Logins SSH exitosos con IP de origen
2. Intentos fallidos con top IPs
3. Paquetes instalados/eliminados
4. Conexiones bloqueadas por firewall
5. Errores en PBS jobs
6. Busqueda libre en un servidor en ventana de tiempo
7. Correlacion temporal con metricas
8. Conteo de eventos por label (rate)
9. Parseo de campos con pattern matching
10. Alertas sobre patrones en logs
### 69. Alertas sobre logs: las reglas que habrian pillado el backdoor en minutos
- No olvidar: alertas concretas en LogQL que habrian detectado este incidente:
- Login desde IP fuera de la whitelist de `red_tecnicos`
- Aparicion de `pam_exec` en syslog (el backdoor se registro en PAM)
- Instalacion de paquetes fuera de ventana de mantenimiento
- Mas de 10 intentos fallidos de SSH en 5 minutos
- Cualquier referencia a IPs del C2 en logs de firewall
Incluir las reglas YAML completas listas para copiar y pegar.
### 70. Dimensionar Loki: cuanto disco necesitas para 500 servidores durante un año
- No olvidar: Loki comprime agresivamente (5-10x). 500 servidores generan ~25GB/dia de logs raw, que Loki comprime a ~3-5GB/dia. 30 dias de retencion = ~150GB. 90 dias = ~450GB. 1 año = ~1.5TB. Backend recomendado: filesystem local para empezar, migrar a Minio/S3 para retencion larga. Retencion diferenciada: auth.log 90 dias, syslog 30 dias, dpkg.log 180 dias.
### 71. El diagrama completo: como encajan Netbox, VictoriaMetrics, Loki y Grafana
- No olvidar: diagrama de arquitectura del stack completo decidido. Netbox (SSOT) alimentado por ICSManager. VictoriaMetrics (metricas) con vmagent, node_exporter, pbs-exporter, pve_exporter. Loki (logs) con Alloy en cada servidor. Grafana como UI unica para todo. Alertas a Telegram/email. VM de monitoring: 4 vCPU, 8GB RAM, 400GB disco. Impacto por servidor de produccion: ~50MB RAM.
---
## Anexos sugeridos
### A. Script de auditoria rapida para servidores Linux
- No olvidar: compilar todos los comandos de deteccion usados en este incidente en un script ejecutable que genere un informe automatico.
### B. Plantilla de reglas de firewall para Proxmox Backup Server
- No olvidar: incluir la configuracion de firewall completa recomendada con politica DROP, whitelist de servicios necesarios, y bloqueo de puertos de mineria/C2.
### C. Playbook de respuesta a incidentes para infraestructura Proxmox
- No olvidar: checklist imprimible con los pasos de investigacion, contencion, erradicacion y recuperacion adaptados a entornos Proxmox con PBS.
---
## Bloque 16: Seguridad como capa de infraestructura - Decisiones de arquitectura
### 72. Wazuh: el guardaespaldas que habria cortado el incidente en minutos
- No olvidar: desglosar exactamente que habria detectado Wazuh y en cuanto tiempo: creacion de `login.sh` (FIM, segundos), modificacion de PAM (FIM, segundos), `ld.so.preload` (rootkit check, segundos), conexion saliente al C2 (log analysis, minutos). El incidente duro 4 dias. Con Wazuh habria durado minutos. Incluir la configuracion FIM concreta para paths de PBS/Proxmox con realtime=yes y report_changes=yes.
### 73. Reglas custom de Wazuh para detectar backdoors PAM en Proxmox
- No olvidar: las 4 reglas XML creadas especificamente para este tipo de ataque: deteccion de pam_exec en ficheros PAM (level 15), deteccion de ld.so.preload (level 15), fichero nuevo en /usr/bin (level 12), curl sospechoso con nohup (level 10). Explicar los niveles de severidad, como se encadenan con sids, y como probarlas antes de ponerlas en produccion.
### 74. auditd como caja negra: el registro que el atacante no puede borrar (si lo envias fuera)
- No olvidar: las reglas de auditd concretas para PBS: monitorizar PAM (-w /etc/pam.d/ -p wa -k pam_changes), SSH config, authorized_keys, crontabs, binarios de sistema, ejecucion de curl/wget/base64. auditd registra pero NO alerta: por eso es complemento de Wazuh, no sustituto. Si los logs de auditd se envian a Loki en tiempo real, el atacante no puede borrar la evidencia.
### 75. Wazuh + Grafana vs Wazuh Dashboard: por que la seguridad merece su propio panel
- No olvidar: dos opciones de visualizacion. Opcion 1: Wazuh Dashboard (OpenSearch) con modulos especializados de seguridad, requiere 4GB RAM extra pero ofrece la mejor experiencia de analisis. Opcion 2: enviar alertas a Loki y verlas en Grafana junto con metricas y logs, ahorra RAM pero pierde dashboards especializados. Recomendacion: empezar con Dashboard propio. Las alertas criticas van a Telegram igualmente.
### 76. Escaneo de vulnerabilidades en 4 capas: de Wazuh a OpenVAS
- No olvidar: piramide de escaneo con herramienta y frecuencia para cada capa: Wazuh vuln detection (paquetes, continuo), Trivy (imagenes Docker, tras cada pull), Nuclei (servicios web como PBS:8007/PVE:8006/PowerDNS Admin, semanal), OpenVAS (red completa, mensual). No empezar por OpenVAS: es lo mas pesado y lo menos urgente. Wazuh ya cubre el 70% del dia 1.
### 77. Vaultwarden en 30 minutos: eliminar contraseñas compartidas por chat
- No olvidar: despliegue real con docker-compose (un contenedor, 256MB RAM). Configuracion con SIGNUPS_ALLOWED=false tras crear las cuentas iniciales. Que meter primero: contraseñas de root de PBS, usuarios PBS de clientes, API tokens, accesos a paneles PVE, credenciales de Netbox/Grafana. Audit log: quien accedio a que secreto y cuando. Comparar con la alternativa de "el password esta en un .txt en el Telegram del equipo".
### 78. De .env a HashiCorp Vault: la ruta evolutiva de gestion de secretos
- No olvidar: tres fases de madurez. Fase 0 (actual): contraseñas en docker-compose y scripts. Fase 1 (inmediata): ficheros .env con chmod 600 fuera del repo git. Fase 2 (cuando Ansible este en produccion): HashiCorp Vault con secretos que Ansible lee dinamicamente, rotacion automatica de API tokens, PKI interna para certificados. No saltar a Vault antes de tener Ansible funcionando.
### 79. SSH hardening como playbook de Ansible: lo que se aplica el dia 1 en todos los servidores
- No olvidar: el playbook concreto con las 8 directivas criticas: PasswordAuthentication no, KbdInteractiveAuthentication no, PermitRootLogin prohibit-password, MaxAuthTries 3, LoginGraceTime 30, AllowUsers, neutralizacion de cloud-init (99-ssh-hardening.cfg con ssh_pwauth: false), instalacion de Fail2ban. Este playbook es lo primero que se ejecuta contra cada servidor nuevo. Incluir el gotcha de cloud-init que reactiva password auth.
### 80. CrowdSec vs Fail2ban: inteligencia colaborativa contra ataques
- No olvidar: Fail2ban es reactivo y local (solo tu ves tus ataques). CrowdSec es proactivo y colaborativo (bloqueas IPs que atacan a otros antes de que te ataquen a ti). No se excluyen: Fail2ban como primera linea inmediata, CrowdSec como segunda linea con threat intelligence. Despliegue con 3 comandos. Collections especificas: crowdsecurity/sshd, crowdsecurity/linux. Metricas exportables a Prometheus.
### 81. TOTP en Proxmox y PBS: MFA que ya tienes y no usas
- No olvidar: tanto PVE como PBS tienen TOTP integrado de serie. Solo hay que habilitarlo por usuario en la GUI. No requiere instalar nada. Protege contra el escenario exacto de este incidente: contraseña robada pero el atacante no puede usarla sin el segundo factor. Incluir paso a paso de activacion y que hacer si pierdes el dispositivo TOTP (recovery keys).
### 82. Teleport: cuando el equipo crece y SSH directo ya no escala
- No olvidar: a 3 tecnicos con acceso SSH directo funciona. A 10+ tecnicos necesitas saber quien hizo que, en que servidor, y cuando. Teleport centraliza todo el acceso SSH con grabacion de sesiones (puedes "reproducir" lo que hizo cada tecnico), MFA obligatorio, RBAC (junior solo ve, senior modifica), y audit completo. Evaluar a partir de 5+ personas o si hay requisitos de compliance (ISO 27001).
### 83. Dimensionar la seguridad: cuanto cuesta en recursos proteger 500 servidores
- No olvidar: desglose completo de recursos. VM Wazuh: 4 vCPU, 8GB RAM, 100GB disco (separada de monitoring). Wazuh agent por servidor: 50-100MB RAM. Vaultwarden: contenedor Docker, 256MB RAM. CrowdSec por servidor: 50MB RAM. Fail2ban: 30MB RAM. auditd: ya instalado, 0 extra. Total overhead por servidor de produccion: ~200MB RAM. VM adicional de seguridad: 4 vCPU, 8GB RAM. Comparar con el coste de otro incidente (4 dias de backdoor activo).
---
## Bloque 17: Vulnerabilidades, secretos y SSO - Decisiones de arquitectura
### 84. Wazuh vulnerability detection: el escaner de CVEs que ya tienes y no sabias
- No olvidar: si ya tienes Wazuh desplegado (2.1), el modulo de vulnerability detection viene incluido. Escanea paquetes instalados contra NVD y Debian Security de forma continua. Cuando sale un CVE nuevo que afecta a un paquete en tus servidores, te avisa automaticamente. Cubre el 70% del escaneo de vulnerabilidades sin esfuerzo adicional. Mostrar ejemplo real de alerta: "CVE-2024-XXXX afecta a openssh-server 9.2p1 en ns31787946".
### 85. Trivy para Docker: escanear antes de desplegar, no despues de llorar
- No olvidar: cada imagen Docker es un sistema operativo en miniatura con sus propias vulnerabilidades. `trivy image mariadb:latest` te dice en 5 segundos que CVEs tiene. El caso real del stack de DNS: PowerDNS + MariaDB + Traefik, cada imagen con su set de vulnerabilidades. Integrar en el workflow: antes de `docker compose up`, ejecutar `trivy`. En CI/CD (Forgejo Actions): bloquear despliegue si hay CVEs criticos.
### 86. Nuclei: auditar tus paneles web antes de que lo haga otro
- No olvidar: PBS:8007, PVE:8006, PowerDNS Admin, phpMyAdmin, Grafana, Netbox... todos son paneles web accesibles por red. Nuclei tiene miles de templates que prueban cabeceras de seguridad, endpoints expuestos, configuraciones por defecto, CVEs conocidos de cada software. Ejemplo real: escanear PBS:8007 abierto a internet y ver que encuentra. Programar semanal con Semaphore y alertar solo en criticos/altos.
### 87. VMs Windows de clientes: monitoring sin gestion, responsabilidad sin culpa
- No olvidar: modelo de responsabilidad en hosting Proxmox. Las VMs Linux las gestionais vosotros (Wazuh agent, hardening, parches). Las VMs Windows las administra el cliente. Pero cuando el Windows "se desmadra" (mineria, ransomware, DDoS), vienen a vosotros. Que monitorizar desde fuera sin tocar dentro: trafico anomalo desde el host, consumo de recursos, disponibilidad (Uptime Kuma). Como detectar mineria desde una VM sin agente: patron de trafico a puertos stratum, CPU sostenido al 100% visto desde el hipervisor.
### 88. Custodiar secretos vs reducir secretos: por que necesitas ambas estrategias
- No olvidar: custodiar (Vaultwarden) protege los secretos que existen. Reducir (SSO con Authentik) elimina secretos innecesarios. Con 50 contraseñas distintas, aunque esten en Vaultwarden, cada una es un vector de ataque. Con SSO, pasas a 1 credencial + MFA que abre todo. Las dos estrategias son complementarias: SSO para el dia a dia, Vaultwarden para los secretos residuales (API tokens, root de emergencia, credenciales de clientes).
### 89. Authentik: SSO y MFA centralizado para toda tu infraestructura Proxmox
- No olvidar: Authentik como Identity Provider que unifica el acceso a PVE (OpenID nativo desde PVE 7), PBS (OpenID nativo), Grafana (OAuth2), Netbox (OAuth2), Forgejo (OAuth2), Semaphore (OIDC), Wazuh Dashboard (SAML), Vaultwarden (SSO nativo). Para apps sin SSO nativo (Uptime Kuma, phpMyAdmin), Authentik actua como proxy de autenticacion. Un tecnico, una cuenta, un MFA, acceso a todo. Baja de la empresa = desactivar una cuenta, no 50.
### 90. Authentik primero: por que el Identity Provider se despliega antes que todo lo demas
- No olvidar: leccion aprendida en la planificacion. Si despliegas Grafana, Netbox, Forgejo con contraseñas locales y luego añades Authentik, tienes que reconfigurar cada servicio. Si despliegas Authentik primero (dia 1 del servidor nuevo), cada servicio nace ya con SSO. El orden correcto para infraestructura desde cero: Forgejo (git) -> Authentik (identidad) -> todo lo demas ya con SSO. Aplicable a cualquier migracion de infra.
### 91. Proxmox VE y PBS con OpenID Connect: eliminar contraseñas locales de los paneles
- No olvidar: tanto PVE como PBS soportan OpenID Connect de serie. Configurar Authentik como proveedor, crear realm OIDC en PVE/PBS, y los tecnicos entran con su cuenta centralizada + MFA. Las cuentas locales (`root@pam`) se mantienen solo para emergencias (password en Vaultwarden). Paso a paso completo de la integracion con capturas.
### 92. La ruta de .env a HashiCorp Vault pasando por Authentik
- No olvidar: evolucion completa de gestion de secretos en 4 fases. Fase 0 (actual): passwords en docker-compose y scripts. Fase 1 (dia 1): ficheros .env con chmod 600 + Vaultwarden para el equipo. Fase 2 (mes 1): Authentik SSO reduce de 50 a ~10 secretos residuales. Fase 3 (mes 6+): HashiCorp Vault para secretos de maquinas (Ansible, CI/CD, rotacion automatica). Cada fase es independiente y aporta valor sin necesitar la siguiente.
### 93. Infraestructura desde cero: el orden optimo para desplegar 15 servicios en una semana
- No olvidar: documentar el orden real de despliegue decidido para el servidor nuevo, basado en dependencias. Dia 1: Forgejo + Authentik + Vaultwarden (fundacion). Dia 2: Wazuh + VictoriaMetrics + Grafana (visibilidad). Dia 3: Loki + Alloy + Netbox (observabilidad). Dia 4: Semaphore + playbooks base (automatizacion). Cada servicio nace con SSO, logs centralizados, y monitoring desde el minuto 0. Comparar con el enfoque clasico de "primero funcionar, luego securizar".
---
## Bloque 18: Acceso SSH y bastion - Decisiones de arquitectura
### 94. Por que descartamos Teleport: cuando el open source no es tan open
- No olvidar: Teleport Community es AGPL-3.0, que no es lo mismo que Apache o MIT. Sigue el patron de empresas que empiezan open y migran features a enterprise (HashiCorp/Terraform, Redis, MongoDB). Ademas requiere un cliente propietario (`tsh`) en vez de SSH estandar, lo que complica Ansible y el workflow diario. Alternativa: bastion SSH puro con grabacion, usando herramientas estandar que llevan 20 años funcionando y no cambian de licencia.
### 95. Bastion SSH con grabacion: toda sesion registrada con SSH estandar
- No olvidar: el bastion es una VM minima (1 vCPU, 1GB RAM) que actua como punto unico de entrada SSH. Usa `ForceCommand` con `script`/`asciinema` para grabar cada sesion completa (teclas, output, timing). Las grabaciones van a Loki para busqueda centralizada. Los servidores destino solo aceptan SSH desde la IP del bastion (iptables DROP al resto). No hay forma de saltarse el bastion. Todo con OpenSSH estandar, sin clientes especiales.
### 96. ProxyJump (-J): la feature de SSH que cambia las reglas del juego
- No olvidar: OpenSSH `ProxyJump` (flag `-J`) permite usar un bastion de forma totalmente transparente. Disponible desde OpenSSH 7.3 (2016), funciona en Linux, macOS, Windows 10/11, iTerm, MobaXterm, WinSCP. Configurando `~/.ssh/config` con `ProxyJump bastion` una sola vez, el tecnico escribe `ssh servidor.infra` y el salto es invisible. Ansible funciona sin cambios. SCP funciona sin cambios. Es SSH normal al 100%.
### 97. SSH solo desde el bastion: como blindar el acceso con una regla de firewall
- No olvidar: la regla mas simple y mas efectiva: `iptables -A INPUT -p tcp --dport 22 -s IP_BASTION -j ACCEPT` + `iptables -A INPUT -p tcp --dport 22 -j DROP`. Se aplica via Ansible a cada servidor nuevo. Resultado: aunque un atacante tenga la clave SSH, no puede conectar directamente a ningun servidor. Tiene que pasar por el bastion, que graba todo. Combinar con Fail2ban y CrowdSec en el propio bastion.
### 98. Fail2ban + CrowdSec: defensa reactiva y proactiva combinadas
- No olvidar: Fail2ban es reactivo y local (banea IPs que fallan contra TU servidor). CrowdSec es proactivo y colaborativo (banea IPs que atacan a OTROS antes de que te ataquen a ti). No se excluyen, se complementan. Fail2ban como primera linea inmediata (dia 1), CrowdSec como segunda linea con threat intelligence (semana 2). CrowdSec exporta metricas a Prometheus, asi que aparece en vuestros dashboards de Grafana.
### 99. El flujo completo de acceso de un tecnico: de Authentik al servidor pasando por el bastion
- No olvidar: documentar el flujo completo end-to-end. Paneles web: tecnico → Authentik SSO → MFA → acceso a PVE/PBS/Grafana/Netbox. SSH: tecnico → ssh servidor.infra → transparente via bastion → sesion grabada → auditd registra dentro → Wazuh vigila. Secretos: tecnico → Vaultwarden (SSO via Authentik) → buscar credencial de cliente. Un solo tecnico, una cuenta, visibilidad total de todo lo que hace.
### 100. Windows de clientes en tu infraestructura: responsabilidad sin culpa
- No olvidar: modelo de responsabilidad claro. VMs Linux: gestionadas por nosotros (Wazuh, hardening, parches). VMs Windows: administradas por el cliente. Pero cuando "se desmadran" vienen a nosotros. Que podemos ver sin tocar dentro: trafico anomalo desde el hipervisor (mineria, C2, DDoS), consumo de recursos, disponibilidad (Uptime Kuma). Detectar mineria desde fuera: patron de trafico a puertos stratum, CPU al 100% sostenido visto desde PVE. Documentar limites de responsabilidad en contrato.
---
## Bloque 19: Automatizacion - De scripts en /root a infraestructura como codigo
### 101. Por que Ansible y no Terraform cuando tus servidores son permanentes
- No olvidar: Terraform/OpenTofu/Pulumi brillan cuando creas y destruyes infraestructura continuamente (cloud, entornos efimeros, CI/CD). Si tus servidores son fisicos dedicados con VMs que viven meses o años, Ansible cubre el 100%: configura lo que ya existe, no necesita crear y destruir. Descartar Terraform no es ignorancia, es saber cuando NO usarlo. Si algun dia necesitais crear 50 VMs identicas de golpe, reevaluar.
### 102. Ansible sin experiencia: la ruta de aprendizaje para sysadmins que ya saben SSH
- No olvidar: si ya sabes hacer `ssh servidor apt upgrade`, ya sabes el 30% de Ansible. Ruta realista: semana 1 (inventario estatico + primer playbook apt upgrade), semana 2 (copiar playbook de hardening SSH ya preparado + aprender roles), semana 3 (Semaphore para ejecutar desde navegador), semana 4 (inventario dinamico Netbox). No intentar automatizar todo el dia 1. Empezar con lo que ya se sabe y crecer.
### 103. El playbook bootstrap-server: un comando para que un servidor nazca seguro
- No olvidar: el primer playbook real no es para servidores existentes, es para preparar cada servidor nuevo antes de recibir VMs. Un solo `ansible-playbook bootstrap-server.yml` ejecuta en secuencia: hardening SSH + Fail2ban + CrowdSec + Wazuh agent + auditd + node_exporter + Alloy + firewall SSH-solo-bastion + Lynis baseline. El servidor nace seguro, monitorizado, con logs centralizados. Comprar con el enfoque manual: 2 horas de checklist vs 5 minutos de playbook.
### 104. Semaphore: Ansible con boton para el equipo que no quiere terminal
- No olvidar: Semaphore es una UI web para Ansible. El junior pulsa "Ejecutar hardening", Semaphore lanza el playbook, muestra el resultado, y queda en el audit log. Sin necesidad de saber sintaxis de ansible-playbook. Con SSO de Authentik (misma cuenta que todo). Scheduling integrado (reemplaza cron jobs). Notificaciones por webhook a Telegram si un playbook falla. 512MB RAM, un contenedor Docker. La API REST permite integracion con ICSManager para provisionamiento automatico.
### 105. Semaphore API + ICSManager: cuando el comercial vende y el servidor se provisiona solo
- No olvidar: flujo completo end-to-end: comercial vende 100GB de backup → ICSManager llama API Netbox (crea device + custom fields) → ICSManager llama API Semaphore (lanza playbook pbs-customer.yml con variables) → Ansible crea dataset ZFS, datastore PBS, usuario, ACL, sync job, verify job → Semaphore reporta OK → facturacion activa el servicio. Ningun tecnico interviene. Todo con audit log. El script `modificar.sh` de /root transformado en un flujo automatico empresarial.
### 106. Forgejo que ya tienes: ampliar el git de desarrollo a infraestructura
- No olvidar: si ya teneis Forgejo para proyectos de desarrollo, no hay que desplegar nada nuevo para infraestructura. Solo crear repos nuevos: `infra/ansible-playbooks`, `infra/pbs-scripts` (migrar de /root), `infra/monitoring-config`, `infra/docker-stacks`. Si el servidor se pierde, toda la operativa se recupera con `git clone`. Activar branch protection en main + review obligatorio para repos de infra: nadie modifica un playbook de hardening sin que otro lo revise.
### 107. Forgejo Actions: CI/CD para infraestructura sin salir del ecosistema
- No olvidar: Forgejo Actions es compatible con GitHub Actions. Con un runner self-hosted, cada push a un playbook ejecuta ansible-lint automaticamente (valida sintaxis antes de aplicar). Evita el "lance el playbook y rompio 50 servidores por un typo en YAML". No hace falta Jenkins ni GitLab CI. Empezar con lint automatico, evaluar deploy automatico cuando el equipo tenga confianza.
### 108. Branch protection: el code review que habria evitado romper produccion
- No olvidar: un playbook de Ansible con un error puede dejar 500 servidores sin SSH. Branch protection en Forgejo (gratis, ya integrado): nadie hace push directo a main, todo va por pull request, al menos 1 persona revisa antes de mergear. Combinado con ansible-lint en CI, los errores se pillan antes de tocar produccion. Coste: 0 euros, 5 minutos de configuracion. Beneficio: no romper 500 servidores a la vez.
### 109. Git como backup de tu operativa: si pierdes el servidor no pierdes los scripts
- No olvidar: todos los scripts de /root (modificar.sh, lista.sh, gc_jobs.sh, verify_jobs.sh, status_disk.sh, enable-maintenance.sh, disable-maintenance.sh) existen solo en un servidor sin control de versiones. Si ese servidor muere, se pierde toda la operativa. Moverlos a Forgejo es un backup inmediato. Si un tecnico modifica un script y rompe algo, `git revert` en 5 segundos. Si quieres saber que cambio y cuando, `git log`. Coste: 1 hora de trabajo. No hay excusa.
---
## Bloque 20: Orquestacion de jobs y cierre de Capa 3
### 110. Cuando los cron jobs de PBS colapsan el servidor: controlar concurrencia sin reinventar la rueda
- No olvidar: los GC y verify jobs programados con el scheduling nativo de PBS pueden provocar picos de IO que congestionan el servidor. Solucion: no usar el scheduling nativo, sino scripts que comprueban si hay otro proceso corriendo antes de lanzar uno nuevo. La logica es simple: consulta API → si hay tarea activa, no lances otra → si no hay ninguna, lanza la mas antigua. Semaphore traduce esto directamente: un playbook con esa logica ejecutado cada 15 minutos, con la opcion de "no ejecutar si la ejecucion anterior no ha terminado". Misma logica, con UI y notificaciones.
### 111. Semaphore como reemplazo de cron: visibilidad sin complejidad
- No olvidar: el salto de cron a Semaphore no es un cambio de herramienta, es un cambio de visibilidad. Con cron: si un job falla, queda en un log local que nadie lee. Con Semaphore: fallo visible en la UI + webhook a Telegram + historial completo de ejecuciones. La logica del playbook es identica a la del script bash, solo cambia donde se ejecuta (Semaphore) y donde se ve el resultado (UI web en vez de /var/log). Migracion progresiva: no cambiar todos los cron de golpe, ir migrando uno a uno y validar.
### 112. n8n y workflows reactivos: el pegamento entre sistemas que no se hablan
- No olvidar: n8n no es una herramienta de dia 1, es de mes 3-6. Su valor es conectar sistemas: Grafana detecta disco al 90% → n8n busca el cliente en Netbox → envia email al comercial. Wazuh detecta actividad sospechosa → n8n pasa el evento a un LLM local → el LLM analiza si es falso positivo → si es real, alerta con explicacion en lenguaje claro a Telegram. Todo sin escribir scripts. Pero requiere que Ansible, Semaphore, Wazuh y Grafana ya esten funcionando. No poner n8n antes de tener los bloques basicos.
### 113. n8n con IA: analisis automatizado de eventos de seguridad
- No olvidar: n8n tiene nodos nativos para OpenAI, Ollama (LLM local), y otros modelos. Caso de uso real: Wazuh genera 50 alertas al dia, el 95% son falsos positivos. n8n recoge cada alerta → la pasa a un LLM → el modelo analiza contexto (hora, servidor, tipo de evento, historial) → clasifica como falso positivo o real → solo las reales llegan a Telegram con una explicacion en lenguaje humano. Reduce la fatiga de alertas dramaticamente. Pero esto es avanzado (mes 6+), requiere que el equipo ya tenga criterio para validar las clasificaciones del LLM.
### 114. Resumen de Capa 3: de scripts en /root a infraestructura gestionada
- No olvidar: la Capa 3 completa transforma la operativa actual de "scripts bash sin versionar ejecutados por cron en un servidor" a "playbooks idempotentes en git, ejecutados desde una UI web con SSO, scheduling centralizado, notificaciones de fallo, audit log, y API para integracion con facturacion". Las herramientas: Ansible (sin agente, solo SSH), Semaphore (UI + scheduling + API), Forgejo existente (git + CI/CD), n8n futuro (workflows reactivos). Terraform descartado (servidores permanentes). Recursos nuevos: Semaphore 512MB + n8n 512MB futuro. Forgejo ya desplegado.
---
## Bloque 21: VPN y red - WireGuard como columna vertebral
### 115. Por que WireGuard y no Tailscale/Headscale cuando controlas toda la infra
- No olvidar: Tailscale es fantastico para equipos distribuidos que necesitan zero-config. Pero si controlas los servidores, el vRack, y el firewall, WireGuard puro te da control total sin dependencia de coordination servers externos (Tailscale SaaS) ni capas de abstraccion (Headscale). Un fichero de texto por servidor, modulo de kernel, overhead ~0. Con Ansible para distribuir configs, la "complejidad" de WireGuard desaparece. Si algun dia la escala lo justifica (+500 peers, mesh dinamico), Headscale es la evolucion natural sin cambiar los clientes.
### 116. Tres redes WireGuard: backups, clientes y gestion - cada una con su rol
- No olvidar: no mezclar todo en una sola VPN. Separar en tres redes con propositos distintos: (1) Backup: PBS como WG server, peers solo los PVE que le envian backups, sin forwarding entre peers. (2) Clientes/tecnicos: WG Hub con forwarding controlado por nftables, aislamiento por cliente. (3) Gestion: mesh cifrado sobre vRack para servicios internos (Grafana, Wazuh, Netbox). Cada red tiene su rango IPv6 ULA independiente. Un compromiso en la red de clientes no afecta a la red de gestion.
### 117. IPv6 ULA para redes internas: sin NAT, sin colisiones, infinitas IPs
- No olvidar: todo el direccionamiento WireGuard en IPv6 ULA (fd00::/8). Ventajas: sin NAT (cada peer tiene IP unica directa), espacio ilimitado (un /64 por red = 2^64 direcciones), organizacion clara por funcion (fdab:1234:bkp::/48 backups, fdab:1234:vpn::/48 clientes, fdab:1234:mgmt::/48 gestion). Los PVE remotos con solo IPv4 se conectan al endpoint WG por IPv4, pero dentro del tunel todo es IPv6. WireGuard separa transporte del payload sin problemas.
### 118. PBS como servidor WireGuard: cerrar el 8007 a internet de una vez
- No olvidar: el puerto 8007 de PBS sirve tanto para el dashboard web como para recibir backups (no se pueden separar). Hoy esta abierto a internet. Solucion: cada PBS levanta un WG server cuyos unicos peers son los PVE que le envian backups. PVE configura el storage como [fdab::X]:8007 (IP WG). PBS:8007 deja de escuchar en IP publica. Solo queda expuesto el puerto UDP de WireGuard. Reduccion dramatica de superficie de ataque. Trafico entre fisicos del mismo DC va por vRack a 25Gbps con WG encima (overhead ~3-5%).
### 119. WG Hub con keepalived: alta disponibilidad sin routing dinamico
- No olvidar: el punto debil del hub-spoke es que si el hub cae, todo para. Solucion simple: par de VMs Debian minimal con la misma config WG y keepalived gestionando una VIP (IP flotante). Failover en <2 segundos. Los peers ni se enteran: su endpoint es la VIP que no cambia. No hace falta BGP ni OSPF: a <200 peers, keepalived es mas simple, mas rapido en failover (2 seg vs 5-30 seg OSPF), y no requiere conocimiento de routing dinamico. Evaluar FRRouting solo si se llega a multiples DCs con hubs distribuidos.
### 120. De un gateway por cliente a gateways compartidos: menos VMs, mas control
- No olvidar: el modelo actual (1 VM gateway por cliente con NAT + WG) significa 50 clientes = 50 VMs que mantener, sin HA, cada una consumiendo recursos. Modelo nuevo: 2 VMs WG Hub (par HA) compartidas por todos los clientes, aislamiento con nftables por subnet IPv6 (/64 por cliente). Ventajas: de 50 VMs a 2, HA centralizada, sin NAT (IPv6 directo), gestion centralizada. Riesgo: error en nftables podria exponer trafico entre clientes. Mitigacion: tests automatizados de aislamiento con Ansible (playbook que verifica que cada cliente solo alcanza sus recursos).
### 121. Aislamiento de clientes con nftables: cada /64 es una isla
- No olvidar: en el WG Hub, el ip forwarding esta activado (los peers deben verse entre ellos dentro del mismo cliente). El aislamiento se hace con nftables: regla por subnet que permite forward solo dentro del mismo /64, y DROP por defecto para todo lo demas. Cada cliente tiene su /64 (fdab:1234:vpn:acme::/64). Las VMs, usuarios remotos y mikrotiks del mismo cliente estan en el mismo /64 y se ven. Los de otro cliente: DROP. Panel futuro para que el cliente defina granularidad peer-a-peer dentro de su /64.
### 122. vRack de OVH: privada no significa segura
- No olvidar: el vRack de OVH es una red L2 privada, pero "privada" solo significa que no sale a internet. Dentro del vRack: sin cifrado, sin autenticacion, cualquier servidor puede ver trafico de los demas (ARP spoofing trivial). Si un servidor es comprometido (como ya paso), tiene acceso directo L2 a todos los demas servidores del vRack. Solucion: WireGuard sobre vRack. Mismo cable de 25Gbps, pero con cifrado y autenticacion encima. Overhead minimo (~3-5% CPU). Un servidor comprometido ya no puede esnifar ni alcanzar servicios de otros sin la clave WG.
### 123. wgdashboard: UI y API para WireGuard sin perder el control
- No olvidar: WireGuard puro no tiene UI ni API. wgdashboard es un contenedor Docker que lee y escribe /etc/wireguard/*.conf y recarga WG (wg syncconf). Aporta: dashboard web (peers conectados, trafico, ultimo handshake), API REST (crear/eliminar peers programaticamente), generacion de configs. Integrable con Authentik (proxy de autenticacion delante). La API permite: ICSManager vende backup → API crea peer WG automaticamente. Corre en la VM del WG Hub, no necesita nada mas.
### 124. Fase de arranque VPN: primero tecnicos, luego clientes
- No olvidar: no abrir la VPN a clientes el dia 1. Fase inicial solo con tecnicos internos: montar par HA de WG Hub, crear peers para el equipo, validar acceso a paneles (:8007, :8006, Grafana, etc.), probar aislamiento nftables, verificar failover keepalived. Cuando el modelo este pulido y estable, abrir progresivamente: primero un cliente piloto, luego el resto. Evita exponer un modelo sin probar a clientes de produccion.
---
## Bloque 22: DNS - Cuatro problematicas, una arquitectura
### 125. PowerDNS autoritativo + Technitium resolver: cada uno en lo suyo
- No olvidar: no mezclar roles. PowerDNS Authoritative se queda como autoritativo de zonas de clientes (primario o secundario) y de las zonas nuevas (vpn6.com.es, PTR IPv6). Technitium DNS entra como resolver: resuelve consultas de navegacion de VMs y usuarios WG, con bloqueo configurable por cliente. Technitium reenvia a PowerDNS las consultas de zonas internas (*.vpn6.com.es, zonas de clientes), y al upstream DoH (Cloudflare/Google) para el resto. Dos herramientas, dos roles, sin solapamiento.
### 126. Technitium DNS: resolver multi-tenant con panel por cliente incluido
- No olvidar: la clave de Technitium frente a AdGuard Home o Pi-hole es el multi-tenancy nativo. Cada cliente (identificado por su rango IP WG) tiene su perfil de bloqueo (malware, ads, adult, custom) y puede ver su propio dashboard de queries. Panel web multi-usuario incluido, sin desarrollo custom. API REST completa para automatizacion. Soporta DNSSEC validation y upstream DoH/DoT. Un contenedor Docker, 512MB-1GB RAM.
### 127. Naming automatico: toda IP tiene nombre desde el momento 0
- No olvidar: cada IP que se asigna (WG peer, VM, servidor) debe tener AAAA + PTR operativos inmediatamente. Esquema sobre vpn6.com.es: laptop.david.vpn6.com.es (tecnico), vm-web.acme.vpn6.com.es (VM cliente), oficina.acme.vpn6.com.es (mikrotik). Automatizacion: wgdashboard crea peer → API PowerDNS crea registros. Netbox sincroniza VM desde PVE → netbox-dns crea registros en PowerDNS. Ningun registro DNS manual. El cliente puede pedir usar su dominio propio (vpn.acme-empresa.com → CNAME a acme.vpn6.com.es).
### 128. PVE a DNS sin hookscripts: el camino limpio via Netbox
- No olvidar: PVE no tiene registro DNS nativo. Se puede hacer con hookscripts (vzdump hooks) que llaman a PowerDNS API, pero es fragil (depende del guest-agent, del script, etc.). El camino limpio: netbox-proxmox sincroniza VMs automaticamente desde la API de PVE a Netbox. netbox-dns en Netbox sincroniza los registros a PowerDNS. Si la VM existe en Netbox con IP, tiene DNS. Sin hookscripts, sin fragilidad, Netbox como SSOT.
### 129. DNS como servicio: bloqueo de malware como valor anadido para clientes
- No olvidar: ofrecer DNS resolver con bloqueo de malware/phishing no es solo seguridad, es un servicio diferenciador. El cliente conecta su VM o su oficina por WG y automaticamente navega con proteccion contra dominios maliciosos. Niveles de servicio: basico (solo malware), medio (malware + ads), premium (configurable por el cliente desde su panel Technitium). Puede ser incluido en el servicio base o como upsell. Coste para nosotros: un contenedor Docker de 512MB.
### 130. Pagina de diagnostico self-service: que el cliente compruebe antes de llamar
- No olvidar: desarrollo propio ligero (Flask/FastAPI, un contenedor). El cliente entra (SSO Authentik), la app detecta su IP WG, identifica quien es, y ejecuta checks en tiempo real: WG conectado (handshake reciente), DNS resolviendo, certificado PBS no caducado, PBS:8007 accesible, latencia. Genera informe copiable. Si hay problema, el cliente ya sabe que falla antes de abrir ticket. Reduce tickets de soporte y mejora la experiencia. Prioridad: mes 3+, no es critico para arrancar.
---
## Bloque 23: Proxy inverso y eliminacion de IPv4
### 131. Traefik como punto unico de publicacion: el cliente no necesita IP publica
- No olvidar: las VMs de clientes tienden a no tener IPv4 publica propia. Traefik actua como proxy inverso centralizado: escucha en IPv4+IPv6 publica, y reenvia a la VM del cliente por su IPv6 WG interna. El cliente declara "quiero publicar portal.acme.com", se crea una ruta en Traefik + un AAAA en PowerDNS, y el servicio esta online con SSL en segundos. La VM solo necesita WG IPv6. Menos IPs publicas, menos superficie de ataque, menos coste.
### 132. SSL automatico centralizado: Let's Encrypt sin que el cliente lo toque
- No olvidar: con Traefik, el SSL es automatico via Let's Encrypt (ACME). El cliente no necesita saber que es un certificado ni como renovarlo. Traefik lo pide, lo renueva, y lo sirve. Centralizado: un solo punto donde gestionar certificados, no uno por VM. Si un certificado falla, Grafana alerta (no el cliente). Elimina la categoria completa de tickets "mi certificado ha caducado".
### 133. De IPv4 publica por VM a IPv6-only con proxy: la transicion
- No olvidar: la transicion no es de golpe. Fase 1: servicios nuevos nacen sin IPv4, solo WG IPv6 + Traefik. Fase 2: servicios existentes se migran progresivamente (cambiar DNS del dominio al Traefik, quitar IP publica de la VM). Fase 3: solo Traefik tiene IPv4 publica, las VMs son IPv6-only. Para clientes legacy que necesiten IPv4 entrante por razones tecnicas, Traefik hace el bridge IPv4→IPv6 de forma transparente. No hay flag day.
### 134. Traefik config dinamica con Ansible: alta automatica de servicios
- No olvidar: Traefik lee ficheros YAML de configuracion de un directorio y recarga automaticamente (file watcher). Ansible genera el YAML al dar de alta un servicio de cliente. Flujo: ICSManager → API Semaphore → playbook que crea fichero YAML en Traefik + AAAA en PowerDNS → servicio publicado. Sin reiniciar Traefik, sin tocar la config a mano. Un fichero YAML por servicio de cliente, versionado en Forgejo.
### 135. Resumen de Capa 4: la red como servicio integrado
- No olvidar: la Capa 4 completa transforma la red de "puertos abiertos a internet con IPs publicas por VM" a "todo por WG cifrado, DNS automatico con nombres desde el momento 0, resolver con bloqueo por cliente, y publicacion de servicios sin IPv4 via Traefik". Herramientas: WireGuard + wgdashboard (VPN), PowerDNS (autoritativo existente), Technitium DNS (resolver multi-tenant), Traefik (proxy inverso, ya existente). IPv6 ULA para todo lo interno. Recursos nuevos: 2 VMs WG Hub (1GB total) + Technitium (512MB-1GB). Todo lo demas ya existe o es kernel module.
---
## Bloque 24: Gestion de incidentes y documentacion
### 136. Zammad como centro: integrar el ticketing con el stack de monitoring
- No olvidar: Zammad ya esta en produccion y funciona. No reinventar. Lo que falta es conectarlo con el stack nuevo: SSO Authentik (misma cuenta), webhook desde Alertmanager (alerta no atendida en 15min → crea ticket automaticamente), webhook desde Wazuh (incidente seguridad → ticket critico), integracion con panel diagnostico (cliente adjunta informe), contexto de Netbox visible en el ticket. Zammad tiene API REST completa, todo esto es viable sin desarrollo complejo.
### 137. Telegram como canal de alertas: simple, al movil, funciona
- No olvidar: no complicarse con herramientas nuevas el dia 1. Alertmanager y Wazuh envian a un bot de Telegram. Llega al movil, se ve, se actua. Es lo minimo que funciona. Cuando el equipo necesite historial buscable, contexto compartido, y canales tematicos, se añade Mattermost. Cuando necesite gestion de guardias y escalado, se añade Grafana OnCall. Pero el dia 1, Telegram y Zammad cubren el 90%.
### 138. Mattermost como futuro panel de notificaciones del equipo
- No olvidar: Mattermost no es para chatear (para eso ya hay canales). Es un panel de notificaciones centralizado donde todo el stack vuelca sus eventos: #alertas-criticas (Alertmanager), #seguridad (Wazuh), #backups (Semaphore), #tickets (Zammad). El equipo tiene visibilidad compartida e historial buscable. Un tecnico nuevo lee los canales y tiene contexto inmediato. Pero requiere que el stack este rodando primero. No antes del mes 3.
### 139. Grafana OnCall: gestion de alertas con ciclo de vida real
- No olvidar: la diferencia entre Telegram/Mattermost y Grafana OnCall es el ciclo de vida. En Telegram los mensajes se acumulan y no sabes si alguien lo esta atendiendo. En OnCall: la alerta aparece activa, alguien se la asigna, cuando se resuelve desaparece. Si nadie responde en X minutos, escala al siguiente. Rotacion de guardias automatica. Integrado en Grafana (mismo panel). Open source. Pero requiere guardias formales. No antes del mes 6.
### 140. Outline como wiki del equipo: Notion pero tuyo
- No olvidar: Outline es una wiki moderna self-hosted con interfaz tipo Notion. Edicion colaborativa en tiempo real (dos tecnicos editando el mismo runbook a la vez), busqueda full-text, permisos por coleccion, SSO nativo con Authentik. Estructura: Runbooks (que hacer cuando X pasa), Arquitectura (diagramas, decisiones), Onboarding (primer dia del tecnico), Clientes (info restringida). Convive con Forgejo: Outline para conocimiento operativo, Forgejo para docs que van con el codigo (README, configs, playbooks). ~1GB RAM en Docker.
### 141. Runbooks: la documentacion que salva a las 3am
- No olvidar: un runbook es "que hacer cuando X pasa", paso a paso, escrito para alguien que esta medio dormido a las 3am. Runbooks criticos minimos: servidor nuevo (checklist bootstrap), incidente de seguridad (protocolo de respuesta), disco lleno (limpiar, ampliar, alertar), restore de backup (como, donde, cuanto tarda), failover WG Hub (pasos manuales si keepalived falla). Si no esta escrito, no existe. Si esta en la cabeza de David y David esta de vacaciones, no existe.
### 142. Resumen de Capa 5: gestionar incidentes sin reinventar
- No olvidar: la Capa 5 no añade casi nada nuevo. Zammad ya funciona (solo integrar con SSO y webhooks). Telegram ya funciona (solo conectar Alertmanager y Wazuh). Lo unico nuevo es Outline para documentacion (~1GB RAM). Mattermost y Grafana OnCall quedan como evoluciones futuras cuando el equipo y los procesos lo justifiquen. Prioridad: no cargar de herramientas nuevas, solo conectar las que ya hay y documentar lo critico.
---
## Bloque 25: Almacenamiento y backup: tres capas geograficas
### 143. ZFS en PBS: un dataset por cliente como unidad de gestion
- No olvidar: ZFS no se usa por sus snapshots (PBS gestiona eso nativamente). Se usa porque permite crear un dataset por cliente con quota y reservation independientes, modelo multiplicador 6x (100GB comerciales = 600GB quota). Esto aisla a los clientes entre si: si un cliente llena su quota no afecta a otros. Propiedades optimizadas: recordsize=1M (alineado con chunk size de PBS), compression=lz4 (rapido, buena ratio), atime=off (reduce escrituras parasitas). No se necesitan Sanoid/Syncoid/zrepl: PBS gestiona snapshots y replicacion con sus propios mecanismos.
### 144. Backup de 3 capas geograficas: PVE → PBS1 → PBS2
- No olvidar: una sola capa de backup es insuficiente (OVH Estrasburgo ardio en 2021). Modelo: PVE (Francia, produccion) → PBS1 (Alemania, transito, retencion corta: keep-last:5, keep-daily:3) ← PBS2 (Polonia, archivo, retencion larga: keep-daily:7, keep-weekly:4, keep-monthly:5). Nota: PBS2 TIRA de PBS1, no al reves. Cada capa aplica su politica de retencion independientemente. 3 paises, 3 jurisdicciones, 3 datacenters separados. Si uno cae, los otros siguen intactos.
### 145. PVE no puede borrar: permisos minimos como defensa anti-ransomware
- No olvidar: el usuario PVE en PBS1 tiene solo DatastoreBackup (crear backups) y DatastoreReader (restaurar). NO tiene DatastoreAdmin ni DatastorePowerUser. Si ransomware compromete un PVE, puede crear backups (inofensivo) y restaurar, pero no puede borrar ni podar los existentes. Principio: el servidor que produce los datos nunca tiene permiso para destruirlos en el servidor de backup. Simple, efectivo, sin herramientas adicionales.
### 146. PBS2 invisible: el bunker que nadie puede alcanzar
- No olvidar: PBS2 es el ultimo recurso. Debe ser inalcanzable. Firewall: INPUT solo acepta SSH desde bastion de emergencia + WG desde peer de gestion. OUTPUT solo hacia PBS1:8007 por WG + DNS/NTP. No tiene puertos abiertos a internet. PBS1 no tiene credenciales de PBS2 ni ruta de red hacia el. PVE no sabe que PBS2 existe. Solo PBS2 decide cuando hablar con PBS1 (sync jobs pull). Verify semanal sobre los backups recibidos: si algo llega corrupto se detecta antes de necesitarlo.
### 147. Cuando PBS1 se pierde: procedimiento de recuperacion con hueco de ~1 dia
- No olvidar: si PBS1 (transito) se pierde por fallo de hardware, el procedimiento es: provisionar PBS1 nuevo → PVE empieza a hacer backups frescos al nuevo PBS1 → PBS2 empieza a tirar cuando hay datos. Hueco de ~1 dia sin capa de transito. Durante ese hueco las VMs funcionan normalmente pero no hay backup reciente. PBS2 conserva todas las copias historicas intactas. El riesgo real es que un PVE falle DURANTE ese hueco. Runbook critico: documentar en Outline el paso a paso de reconstruccion de PBS1.
### 148. Cuando PBS2 se pierde: definicion de producto y opcion PBS3
- No olvidar: si PBS2 (archivo) se pierde, se pierden las copias historicas (semanas, meses). PBS1 sigue con retencion corta. PVE sigue haciendo backups. Pero si PBS1 tambien falla → datos perdidos. Esto no es un fallo tecnico a resolver, es una decision de producto: el producto base incluye 2 capas (PBS1+PBS2), clientes criticos que no quieran asumir ese riesgo pueden contratar PBS3 (otra ubicacion, otro proveedor). Documentar claramente en la definicion del producto los riesgos de cada nivel de servicio. El cliente decide segun su criticidad y presupuesto.
### 149. Monitorizar el backup del backup: alertas que no puedes ignorar
- No olvidar: todo este modelo es inutil si nadie se entera de que fallo. Alertas criticas (todas a Telegram + ticket Zammad si no se atiende en 15min): PBSBackupOld48h (VM sin backup en 48h), PBSSyncFailed (sync PBS2←PBS1 fallo), PBSSyncOld48h (PBS2 no sincroniza en 48h), PBSVerifyErrors (verify en PBS2 detecta corrupcion). Alertas warning: DatastoreSpace90 (PBS1 o PBS2 > 90% espacio). La alerta de sync es especialmente critica: si PBS2 deja de sincronizar y nadie lo nota, cuando se necesite la copia estara desactualizada.
### 150. Configs de PVE/PBS a git: saber exactamente que habia cuando algo se pierde
- No olvidar: los datos de VMs estan en PBS (backup). Pero la configuracion del propio nodo (que VMs habia, con que config, que datastores, que usuarios, que red) esta solo en el nodo. Si se pierde, ICSManager sabe que clientes hay pero no el detalle de cada .conf de VM, cada regla de firewall, cada ZFS property. Solucion simple: playbook Ansible que diariamente recoge /etc/pve/ y /etc/proxmox-backup/ de cada nodo y hace commit a un repo de Forgejo. Son ficheros de texto (KB), el diff de cada commit muestra exactamente que cambio. Coste cero: Forgejo ya existe, son KB de texto. Valor enorme: reconstruir un nodo pasa de horas/dias adivinando a minutos leyendo configs exactas. Bonus: si alguien cambia algo manualmente, el diff lo delata.
### 151. Replica ZFS de VMs de gestion a oficina: plan de contingencia fuera de OVH
- No olvidar: toda la infra de gestion (monitoring, Wazuh, Netbox, Authentik) vive en OVH. Si OVH pierde ese servidor, te quedas ciego. Solucion: replicar las VMs criticas por ZFS send/recv incremental cada 4h al servidor Xeon 96GB que ya existe en la oficina. Las VMs estan apagadas, solo se encienden en contingencia. Transporte por WG cifrado. Sync incremental ~1-5 GB cada 4h (factible con fibra). Plan de contingencia: detectar caida → encender VMs en oficina → actualizar DNS/WG → ~10 minutos operativo. No es HA automatico, es plan B manual con runbook en Outline. Coste: cero (hardware existente). Solo replica gestion, no datos de clientes (esos estan en las 3 capas PBS).
### 152. Resumen de Capa 6: almacenamiento y backup sin herramientas extra
- No olvidar: la Capa 6 no introduce herramientas nuevas de software. ZFS ya esta (solo monitorizar con node_exporter existente). PBS gestiona snapshots y replicacion nativamente (Sanoid/Syncoid/zrepl descartados). 4 subcapas: 6.1 ZFS monitoring, 6.2 backup 3 capas geograficas (PVE→PBS1→PBS2, con opcion PBS3 premium), 6.3 configs PVE/PBS a git diariamente (Forgejo, coste 0), 6.4 replica ZFS de VMs de gestion a oficina (servidor existente, coste 0). La seguridad viene de la arquitectura (permisos, aislamiento, pull-not-push, invisibilidad, diversificacion geografica) no de software adicional. Recursos nuevos: PBS2 fisico (Polonia) y las alertas en el stack existente. Todo lo demas ya existe o es coste cero.
---
## Bloque 26: Observabilidad avanzada - de datos a decisiones
### 153. Dashboard por cliente en Grafana: una vista, todo un cliente
- No olvidar: hoy para ver el estado de un cliente el tecnico salta entre 4 herramientas. Con un dashboard Grafana con variable dropdown por cliente, seleccionas "ACME" y ves todo: VMs (UP/DOWN, CPU, RAM, disco), backups (ultimo, estado, verify), storage PBS (uso, tendencia), sync PBS2, eventos Wazuh, conectividad WG. Un solo dashboard, todos los clientes. La variable viene de Netbox (plugin grafana-netbox-datasource) asi que al dar de alta un cliente en Netbox aparece automaticamente en el dropdown. No es un dashboard por cliente, es un dashboard con filtro.
### 154. SLOs/SLIs: medir lo que prometes al cliente
- No olvidar: sin SLIs no sabes si cumples lo que prometes. Definir metricas claras: backup freshness (< 24h), backup success rate (> 99%), verify pass rate (> 99.5%), sync freshness (< 48h), storage headroom (> 15%), VM availability (> 99.5%). Trackear en panel Grafana con semaforo verde/rojo. Alertas cuando un SLO se incumple (diferente de alertas de infra: las de infra dicen "algo falla ahora", las de SLO dicen "estas incumpliendo lo que prometiste"). Cuando el cliente pregunta "como ha ido este mes", tienes datos, no opiniones.
### 155. Capacity planning: anticipar en vez de reaccionar
- No olvidar: VictoriaMetrics tiene predict_linear nativo (Prometheus tambien pero MetricsQL es mas potente). Aplicar a storage PBS: ¿cuantos dias quedan para que ACME llene su quota? Si la respuesta es < 30 dias, alerta warning. Si < 7 dias, alerta critica. Mismo para pool ZFS global. Dashboard con tabla de todos los clientes ordenados por "dias para llenarse". El comercial puede contactar al cliente ANTES de que se llene, no despues. Diferenciador de servicio: "te avisamos cuando necesitas mas espacio, no cuando ya no tienes".
### 156. Informes mensuales automaticos: el cliente recibe datos, no silencio
- No olvidar: un informe mensual automatico por cliente (backups OK, uptime, storage, seguridad) generado con playbook Ansible + template Jinja2 → PDF/HTML. Enviado por email o disponible en Zammad/Outline. El cliente ve que el servicio funciona. El comercial tiene argumento para renovar. El tecnico tiene evidencia si hay disputa. Implementar cuando el stack este maduro (mes 4+). No urgente pero diferenciador enorme: la mayoria de proveedores no envian informes proactivos.
### 157. Grafana org per-client: que el cliente vea sus datos en tiempo real
- No olvidar: Grafana soporta Organizations con RBAC. Cada cliente puede tener acceso de solo lectura a un dashboard con sus metricas. SSO con Authentik (misma cuenta). El cliente ve sus VMs, sus backups, su storage. No ve nada de otros clientes ni de la infra interna. Es un upsell o diferenciador: "te damos acceso a tu panel de monitoring". Implementar mes 3+ cuando los dashboards esten pulidos.
### 158. Correlacion metricas + logs + seguridad: investigar incidentes sin saltar entre herramientas
- No olvidar: Grafana soporta multiples data sources en la misma vista temporal. Dashboard de investigacion: arriba metricas (VictoriaMetrics), centro logs (Loki), abajo eventos de seguridad (Wazuh via Loki). Seleccionas un rango temporal y ves todo sincronizado. Annotations: eventos de Wazuh aparecen como lineas verticales sobre las graficas de metricas. Para que funcione: enviar Wazuh alerts.json a Loki via Alloy (un fichero JSON, Alloy lo recoge como cualquier otro log). La correlacion es visual, no automatica, pero ahorra el 80% del tiempo de investigacion.
### 159. Resumen de Capa 7: observabilidad avanzada sin herramientas nuevas
- No olvidar: la Capa 7 no introduce ninguna herramienta nueva. Todo se construye sobre Grafana + VictoriaMetrics + Loki + Wazuh + Netbox ya desplegados en Capas 1-2. Coste: cero. Son dashboards, queries, recording rules, templates. 5 subcapas: dashboards por cliente (mes 1-2), SLOs/SLIs (mes 2-3), capacity planning con prediccion (mes 2-3), status page + informes (mes 3-4), correlacion avanzada (mes 2-3). Transforma datos crudos (metricas, logs, eventos) en inteligencia operativa (¿como esta el cliente? ¿cumplimos lo prometido? ¿cuando necesitaremos mas disco? ¿que paso exactamente a las 03:15?). La diferencia entre tener datos y usarlos.
---
## Bloque 27: Modelo de VMs, salida a internet y decisiones de producto
### 160. Una VM = un servicio: el patron de caja negra que simplifica todo
- No olvidar: cada servicio con BBDD vive en su propia VM con todo dentro (app + PostgreSQL/MongoDB + Redis, todo Docker). Zammad en una VM, Authentik en otra, Netbox en otra, ICSManager en otra, WildDuck en otra. Un tecnico trabaja en la VM de Zammad con libertad total sin miedo a romper Netbox. Si Zammad falla, reinicias su VM. Para migrar: mueves la VM entera. Para backup: PBS backupea la VM entera (datos incluidos). Para diagnosticar: "la VM Zammad consume IO" → es Zammad. Mas VMs pero operativamente mucho mas simple que una VM con 6 servicios mezclados.
### 161. WildDuck y MongoDB: correo del equipo como servicio dockerizado
- No olvidar: WildDuck (correo del equipo tecnico) corre en su propia VM con MongoDB y Redis dockerizados dentro. Funcionalidad critica: tokens SMTP que usan los PVE para enviar notificaciones de avisos. Si se pierde WildDuck, los PVE dejan de notificar. MongoDB dockerizado es suficiente para correo interno (bajo volumen). Si crece (mas departamentos, clientes con correo), reevaluar si MongoDB necesita VM dedicada. De momento: caja negra, todo dentro, backupeado por PBS.
### 162. CGNAT para IPv4 de VMs: el rango que no colisiona con nadie
- No olvidar: las VMs de clientes necesitan IPv4 para salir a internet (apt, APIs, navegacion). Usar rango CGNAT 100.64.0.0/10 (RFC 6598) en vez de RFC1918 (10.x, 192.168.x). Ventaja: si el cliente conecta su oficina (192.168.1.0/24) por WG, no hay conflicto con la IP de sus VMs. Asignacion: un /24 por cliente (100.64.1.0/24 para ACME, 100.64.2.0/24 para BETA). 64.000 /24 disponibles, sobra. Registro en Netbox IPAM como cualquier otro prefijo.
### 163. Politica de salida restrictiva: puerto 25 bloqueado sin excepciones
- No olvidar: con NAT compartido, un cliente que envia spam blacklistea la IP para todos. Solucion: politica nftables restrictiva en el WG Hub. Permitido: 80, 443 (web), 53 (DNS), 123 (NTP). Puerto 25 (SMTP sin autenticar): BLOQUEADO SIEMPRE, sin excepciones. Puertos 465, 587 (SMTP autenticado): solo a whitelist de servidores conocidos (WildDuck propio, Gmail, etc.). Todo lo demas: bloqueado por defecto, el cliente pide y se evalua. Logs de intentos bloqueados a Loki para detectar abusos.
### 164. IP compartida base vs IP dedicada premium: decision de producto
- No olvidar: el servicio base incluye NAT compartido con IP que puede cambiar sin preaviso y sin garantia de reputacion. Si un cliente necesita IP fija con PTR propio (para enviar email desde sus VMs, por ejemplo), contrata el servicio premium: IP dedicada, si se blacklistea solo le afecta a el. Implementacion trivial: una regla nftables SNAT por cliente premium. Coste de IP adicional en OVH: centimos. Se repercute como servicio premium. Documentar claramente en la definicion de producto.
### 165. Dual-stack por VM: IPv4 sale, IPv6 entra, Traefik publica
- No olvidar: cada VM de cliente tiene dual-stack. IPv4 CGNAT (100.64.x.x) solo para salir (NAT en WG Hub, nunca abierto entrante). IPv6 WG (fdab:...) para acceso entrante controlado (RDP, SSH, lo que el cliente autorice via nftables per-peer). Servicios web publicados via Traefik (sin IP publica en la VM). Tres canales claros, tres propositos distintos. El cliente nunca necesita una IP publica propia.
### 166. Dimensionamiento revisado: de 64 GB a 128 GB RAM
- No olvidar: con el modelo de una VM por servicio, las VMs de gestion pasan de 30-36 GB (servicios compartidos) a 40-52 GB (cada uno en su VM). Con PVE host overhead (~4 GB) y margen de crecimiento (Mattermost, n8n, Grafana OnCall futuro), 64 GB queda justo. 128 GB da margen para 3-5 años sin preocuparse. CPU: 8-12 cores / 16-24 threads sobra (las VMs son IO-bound, no CPU-bound). Disco: 2x2TB NVMe en ZFS mirror para IO de Loki + VictoriaMetrics + OpenSearch.
---
## Bloque 28: Gestion multi-cluster y filtrado de correo
### 167. Proxmox Datacenter Manager (PDM): gestion multi-cluster desde un solo panel
- No olvidar: con multiples PVE en distintos datacenters, gestionar cada uno por separado es tedioso y propenso a errores. PDM centraliza la vista de todos los clusters PVE en una sola interfaz web. Funcionalidad clave: migracion cross-cluster (mover VMs de un PVE en Francia a otro en Alemania sin downtime manual). Tambien: inventario centralizado de recursos, alertas globales, y busqueda de VMs en cualquier cluster. Se despliega como VM ligera (1 vCPU, 1-2 GB RAM). Complementa a Netbox (PDM es operacion en tiempo real, Netbox es inventario planificado). No sustituye a Ansible para configuracion.
### 168. Migracion cross-cluster con PDM: mover VMs entre datacenters
- No olvidar: escenario real: un cliente tiene VMs en PVE-Francia y queremos moverlas a PVE-Alemania (mantenimiento, mejor latencia, o descomision). Sin PDM: export OVA + import manual + reconfigurar red. Con PDM: seleccionar VM → migrar a cluster destino → PDM orquesta la copia de discos y reconfiguracion. Requisitos: WireGuard entre clusters (ya tenemos), storage compatible en destino, mappings de red configurados. No es instantaneo (depende del tamaño del disco), pero es automatizado y sin errores manuales.
### 169. Proxmox Mail Gateway (PMG): anti-spam y anti-virus delante de WildDuck
- No olvidar: WildDuck acepta correo pero no tiene filtrado anti-spam/anti-virus nativo robusto. PMG se coloca delante como MX relay: MX → PMG → WildDuck. PMG incluye SpamAssassin (anti-spam con scoring), ClamAV (anti-virus), greylisting, SPF/DKIM/DMARC checks, y una interfaz de quarantine donde los usuarios ven sus correos retenidos. Para correo saliente: PMG verifica que el correo saliente no sea spam (protege la reputacion de nuestra IP). Recurso modesto: 1-2 vCPU, 2-3 GB RAM. Solo tiene sentido cuando WildDuck se abra a mas usuarios/departamentos.
### 170. PMG como capa de defensa del correo: reglas, quarantine y reporting
- No olvidar: PMG permite crear reglas por dominio, remitente, destinatario. Ejemplo: correo de dominios .ru → spam score +5. Correo con adjuntos .exe → quarantine directa. La interfaz de quarantine es self-service: el usuario revisa sus correos retenidos sin molestar al admin. Reports diarios/semanales por email. Integracion con Grafana: metricas de correos procesados, spam rate, virus detectados → dashboard de salud del correo. Greylist reduce spam en ~80% sin false positives. Configuracion via API para automatizar con Ansible.
---
## Bloque 29: IA y agentes para operaciones
### 171. Claude Code en el bastion: copiloto de infraestructura para tecnicos
- No olvidar: instalar Claude Code (CLI) en la VM Bastion. El tecnico hace SSH al bastion y usa Claude Code como copiloto conversacional. Tiene acceso a los repos de playbooks, CLIs de PBS/ZFS, APIs de Netbox/PVE. Casos de uso: diagnosticar GC lentos, generar playbooks, analizar alertas Wazuh, documentar scripts heredados, construir timelines de incidentes. No es un demonio ni un servicio: se ejecuta solo cuando el tecnico lo lanza. Coste: solo API key (~$20-50/mes segun uso). Recurso: despreciable (va en Bastion existente).
### 172. Agentes de IA especializados: n8n + Claude API en vez de un agente general
- No olvidar: no desplegar un agente general con acceso al sistema (tipo OpenClaw). En su lugar: workflows de n8n que se disparan por triggers (alerta, cron, webhook), recopilan contexto de APIs (VictoriaMetrics, Loki, Netbox), llaman a Claude API con prompt especializado, y generan outputs (tickets Zammad, informes Outline, MRs en Forgejo). Ventajas: scope minimo, read-only, auditable, sin acceso shell, humano aprueba antes de actuar. Cada agente es un workflow con 5-6 nodos, no un servicio nuevo.
### 173. Agente de triaje de alertas: de "disco lleno" a diagnostico con contexto
- No olvidar: el agente con mayor ROI. Alertmanager dispara webhook → n8n recopila metricas (VictoriaMetrics, 2h), logs (Loki, 30min), inventario (Netbox: cliente, SLA) → Claude API analiza con prompt que incluye arboles de decision para problemas comunes → crea ticket Zammad con severidad, diagnostico y acciones recomendadas. Ejemplo: "GC de ACME lleva 26h. 340 snapshots, ultimo exitoso hace 12 dias. Verificar sync job concurrente." Un tecnico junior recibe un ticket ya triado en vez de una alerta cruda.
### 174. Agente de capacity planning: prediccion semanal de espacio
- No olvidar: cron semanal, consulta todas las metricas de disco, calcula tendencias 30/60/90 dias, genera tabla priorizada en Outline: cliente, usado%, quota, tendencia, dias hasta lleno, accion. El tecnico lee un informe de 1 pagina los lunes en vez de revisar 100 datastores manualmente. Detecta crecimiento anomalo ("GAMMA crecio un 15% esta semana, normal es 2%"). Usa predict_linear de VictoriaMetrics como input.
### 175. Agente de seguridad: analisis automatizado de alertas Wazuh
- No olvidar: Wazuh genera muchas alertas, la mayoria son ruido. El agente recibe alertas nivel ≥10, recopila contexto (logs, eventos correlacionados, baseline del servidor), y clasifica: falso positivo (con justificacion), incidente real (con pasos de respuesta del playbook), o indeterminado (que verificar manualmente). Reduce la fatiga de alertas del equipo. Usa Opus (maximo razonamiento) en vez de Sonnet por la criticidad.
### 176. Por que descartamos OpenClaw para infraestructura
- No olvidar: OpenClaw (145k+ estrellas GitHub, agente IA open-source) fue evaluado y descartado. Razones: (1) Vulnerabilidades de seguridad documentadas - prompt injection via skills (demostrado por Cisco), ClawJacked (control remoto via WebSocket). Nosotros acabamos de sufrir un credential stealer con acceso shell; poner un agente IA con acceso shell y vulnerabilidades conocidas seria repetir el error. (2) Modelo inadecuado: es un demonio general con acceso amplio, nosotros necesitamos agentes especializados bajo demanda con scope minimo. (3) Complejidad innecesaria: requiere MongoDB, gateway, canales; nosotros ya tenemos n8n + Zammad + Mattermost. (4) Gobernanza incierta: creador se unio a OpenAI, China restringio su uso. Reevaluar si madura en seguridad.
### 177. Principios de seguridad para agentes de IA en produccion
- No olvidar: cinco reglas inquebrantables. (1) Read-only por defecto: agentes consultan APIs pero nunca ejecutan comandos en produccion. (2) Humano en el bucle: las acciones son recomendaciones, un humano aprueba. (3) Scope minimo: cada agente solo accede a las APIs que necesita, no "acceso a todo". (4) Auditabilidad total: ejecuciones en n8n + logs en Loki. (5) Coste controlado: Sonnet para rutina, Opus solo para seguridad. Si un agente necesita acceso de escritura a produccion, no es un agente: es un playbook de Ansible con aprobacion en Semaphore.