Upload files to "/"

This commit is contained in:
davidtoribioeu 2026-03-14 19:32:30 +00:00
commit edefaf9b69
5 changed files with 1746 additions and 0 deletions

View file

@ -0,0 +1,297 @@
# Ecosistema de herramientas para administradores de infraestructura Proxmox/PBS
> Guia de herramientas recomendadas para equipos que gestionan entre 100 y 500 servidores Proxmox VE, Proxmox Backup Server, y servicios asociados. Organizado por capas funcionales, de lo mas urgente a lo mas estrategico.
---
## Capa 1: Visibilidad - Si no lo ves, no existe
### 1.1 Inventario y CMDB
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Netbox** | Inventario de servidores, IPs, racks, cableado, VMs, datastores. SSOT (Single Source of Truth) de toda la infra. | 100-5000+ |
| **GLPI** | Inventario + ticketing + gestion de activos. Mas orientado a ITIL. | 100-1000 |
| **Snipe-IT** | Gestion de activos hardware (servidores fisicos, discos, tarjetas de red). Complementa a Netbox. | 100-500 |
- No olvidar: sin un inventario centralizado, a 100+ servidores no sabes que tienes, donde esta, ni que version corre. En este incidente, la documentacion en CLAUDE.md era el unico inventario, y eso no escala.
### 1.2 Monitoring de infraestructura
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Prometheus + Grafana** | Metricas de CPU, RAM, disco, red, ZFS, PBS jobs. Alertas basadas en umbrales. Stack estandar de la industria. | 100-10000+ |
| **Victoria Metrics** | Alternativa a Prometheus con menor consumo de recursos y mejor retencion a largo plazo. Drop-in compatible. | 500-10000+ |
| **pve-exporter** | Exportador Prometheus especifico para Proxmox VE. Extrae metricas de VMs, nodos, storage. | Cualquiera |
| **Zabbix** | Monitoring todo-en-uno con autodiscovery, templates para Proxmox y ZFS, alertas, mapas de red. Mas pesado pero muy completo. | 100-5000+ |
| **Uptime Kuma** | Monitoring ligero de disponibilidad (HTTP, TCP, DNS, ping). Ideal para servicios criticos. Alertas por Telegram/email. | 10-500 |
| **Checkmk** | Monitoring con agente, autodiscovery agresivo, templates de ZFS y Linux. Buena alternativa a Zabbix. | 100-5000+ |
- No olvidar: el DNS en la VM 135241 estuvo caido por disco lleno sin que nadie se enterase. A 100 servidores, esto pasa constantemente si no hay monitoring. Metricas minimas obligatorias: espacio en disco (alerta al 80%), estado de ZFS pools, estado de jobs PBS (GC, verify, sync), disponibilidad de servicios.
### 1.3 Monitoring de backups (PBS especifico)
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Proxmox Backup Metrics (influxdb)** | PBS puede enviar metricas nativas a InfluxDB. Verificar que todos los PBS estan reportando. | Cualquiera |
| **Script personalizado + Prometheus pushgateway** | Exportar estado de GC jobs, verify jobs, sync jobs, espacio por datastore, ultimo backup exitoso por VM. | 100-500 |
| **Grafana dashboards para PBS** | Dashboards dedicados: ultimo backup por cliente, jobs fallidos, ocupacion por datastore vs quota, tendencia de crecimiento. | Cualquiera |
| **Alerta "ultimo backup > 48h"** | Si una VM no tiene backup en 48h, algo esta mal. Esta alerta sola previene el 80% de los problemas de backup. | Cualquiera |
- No olvidar: gestionar 100+ PBS sin un dashboard centralizado de estado de backups es volar a ciegas. El mayor riesgo no es perder un backup, es no darte cuenta de que lo has perdido.
### 1.4 Logs centralizados
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Grafana Loki + Promtail** | Agregacion de logs ligera. Misma interfaz que Grafana para metricas. Barato en recursos. | 100-1000 |
| **Graylog** | Logs centralizados con busqueda, alertas, dashboards. Buena relacion potencia/complejidad. | 100-5000 |
| **ELK Stack (Elasticsearch + Logstash + Kibana)** | El estandar para logs a gran escala. Potente pero costoso en recursos. | 500-10000+ |
| **Vector (de Datadog)** | Recolector y router de logs ultraligero. Reemplaza a Logstash/Promtail con menor overhead. | Cualquiera |
- No olvidar: en este incidente, los logs de auth estaban solo en el servidor comprometido. Un atacante puede borrar logs locales. Con logs centralizados, aunque comprometa el servidor, la evidencia ya esta en otro sitio. Minimo centralizar: auth.log, syslog, logs de PBS, logs de firewall.
---
## Capa 2: Seguridad - Lo que nos habria salvado
### 2.1 Deteccion de intrusiones y file integrity
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **OSSEC / Wazuh** | HIDS (Host Intrusion Detection). Monitoriza cambios en ficheros, analiza logs, detecta rootkits, alerta en tiempo real. Wazuh es el fork activo con dashboard. | 100-10000+ |
| **AIDE** | File integrity monitoring. Genera una base de datos de checksums y alerta si algo cambia en /usr/bin, /etc/pam.d, etc. Ligero. | 10-500 |
| **Tripwire** | Similar a AIDE pero comercial. Version open source disponible. | 100-1000 |
| **auditd + aureport** | Auditoria del kernel de Linux. Registra quien cambio que fichero, que proceso abrio que socket. Ya viene instalado, solo hay que configurarlo. | Cualquiera |
| **Lynis** | Auditoria de seguridad y hardening. Escanea el sistema y da puntuacion con recomendaciones. Ideal para linea base. | Cualquiera |
- No olvidar: **Wazuh habria detectado este incidente en minutos**, no en 4 dias. Habria alertado al detectar: creacion de `/usr/bin/login.sh`, modificacion de `/etc/pam.d/common-auth`, creacion de `/etc/ld.so.preload`, y conexion saliente a una IP desconocida. Es la herramienta de mayor impacto para este escenario.
### 2.2 Escaneo de vulnerabilidades
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **OpenVAS / Greenbone** | Escaner de vulnerabilidades de red. Detecta servicios expuestos, CVEs, configuraciones debiles. | 100-1000 |
| **Trivy** | Escaner de vulnerabilidades para contenedores Docker, imagenes, y ficheros de configuracion. Rapido y ligero. | Cualquiera |
| **Nuclei** | Escaner de vulnerabilidades basado en templates. Miles de checks para servicios web, APIs, paneles de admin. | Cualquiera |
- No olvidar: escanear regularmente desde fuera (que ve un atacante) y desde dentro (que tiene cada servidor). Automatizar con cron semanal y alertar solo en criticos/altos.
### 2.3 Gestion de secretos y credenciales
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **HashiCorp Vault** | Gestion centralizada de secretos: contraseñas, API keys, certificados. Rotacion automatica. Audit log. | 100-10000+ |
| **Bitwarden / Vaultwarden** | Gestor de contraseñas para el equipo. Para credenciales que necesitan acceso humano (paneles web, etc). | Cualquiera |
| **SOPS (Mozilla)** | Cifrado de secretos en ficheros (YAML, JSON). Ideal para secretos en repos git. | Cualquiera |
- No olvidar: en los docker-compose encontrados habia contraseñas en texto plano (`PDNS_API_KEY=secret`, `MYSQL_ROOT_PASSWORD`). A 100+ servidores con multiples equipos, los secretos en texto plano son una bomba de relojeria.
### 2.4 Acceso y autenticacion
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Teleport** | Acceso SSH centralizado con grabacion de sesiones, MFA, RBAC, y audit log. Reemplaza SSH directo. | 50-5000+ |
| **Boundary (HashiCorp)** | Acceso seguro a servicios sin exponer la red. Session recording. Complementa Vault. | 100-5000+ |
| **FreeIPA / Keycloak** | Directorio central de usuarios, SSO, MFA. Elimina usuarios locales en cada servidor. | 100-5000+ |
| **Fail2ban** | Bloqueo automatico de IPs con intentos fallidos. Basico pero efectivo. Deberia estar en todos los servidores. | Cualquiera |
| **Yubikey / MFA hardware** | Segundo factor fisico para SSH y paneles web. Elimina el riesgo de contraseñas robadas. | Cualquiera |
- No olvidar: en este incidente, aunque la contraseña fue robada, el firewall limitaba SSH por IP. Pero si el atacante hubiera estado en una IP permitida (o si hubiera usado la contraseña en el panel web PBS:8007 que estaba abierto a todos), habria entrado. MFA habria bloqueado el acceso incluso con la contraseña robada.
---
## Capa 3: Automatizacion - Lo que mantiene la cordura a escala
### 3.1 Gestion de configuracion
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Ansible** | Automatizacion sin agente. Ideal para Proxmox: provisionar VMs, configurar PBS, desplegar reglas de firewall, aplicar hardening. Ya se usa en este entorno (clave SSH de `david@ansible`). | 10-5000+ |
| **Ansible Semaphore** | UI web para Ansible. Permite al equipo ejecutar playbooks sin acceso SSH directo. Audit log de quien ejecuto que. | 50-500 |
| **Terraform + provider Proxmox** | Infraestructura como codigo. Definir VMs, redes, storage en ficheros versionados. Reproducibilidad total. | 50-5000+ |
| **Pulumi** | Alternativa a Terraform usando lenguajes reales (Python, Go, TypeScript). Mas flexible para logica compleja. | 50-5000+ |
- No olvidar: el script `modificar.sh` es el embrion de automatizacion. A 100+ servidores, eso deberia ser un playbook de Ansible idempotente que garantice que la configuracion de cada PBS es consistente. Si un atacante modifica PAM en un servidor, el proximo run de Ansible lo revierte.
### 3.2 CI/CD para infraestructura
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Gitea / Forgejo** | Repositorio git auto-alojado para scripts, playbooks, configuraciones. No depender de GitHub para infra critica. | Cualquiera |
| **Woodpecker CI** | CI/CD ligero, auto-alojado. Ejecuta playbooks de Ansible automaticamente al hacer push. | 10-500 |
| **GitLab CE** | Repositorio + CI/CD + registry + wiki. Todo en uno. Mas pesado pero muy completo. | 50-5000+ |
- No olvidar: todos los scripts de `/root/` (modificar.sh, lista.sh, gc_jobs.sh, etc.) deberian estar en un repositorio git con versionado, code review, y despliegue automatico. Si el servidor se reinstala, se recupera toda la automatizacion.
### 3.3 Orquestacion y scheduling
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Rundeck** | Ejecucion de jobs en multiples servidores con UI, RBAC, scheduling, y audit log. Ideal para operaciones como GC masivo. | 50-1000 |
| **AWX (Ansible Tower open source)** | Interfaz web para Ansible con inventario dinamico, scheduling, RBAC. Mas completo que Semaphore. | 100-5000+ |
| **n8n** | Automatizacion de workflows (si pasa X, haz Y). Conectar alertas con acciones: si Wazuh detecta intrusion, bloquear IP en firewall. | Cualquiera |
- No olvidar: los cron jobs actuales (`pbs-gc-oldest.sh` cada 30min, `pbs-verify-oldest.sh` cada 2h) funcionan en un solo servidor. A 100+ servidores, necesitas orquestacion centralizada que distribuya los jobs, evite colisiones, y reporte resultados.
---
## Capa 4: Red y conectividad
### 4.1 VPN y acceso seguro
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **WireGuard** | VPN punto a punto ultraligera. Ideal para conectar PBS con servidores remotos por vRack o internet. Reemplaza las IPs publicas expuestas. | Cualquiera |
| **Tailscale / Headscale** | VPN mesh basada en WireGuard con zero-config. Cada servidor se une a la red. Headscale es la version self-hosted. | 10-1000 |
| **Nebula (Slack/Defined)** | Overlay network con certificados. Cada nodo tiene identidad criptografica. Muy escalable. | 100-10000+ |
| **Netbird** | VPN mesh self-hosted con SSO integration. Alternativa a Tailscale. | 50-1000 |
- No olvidar: el PBS actual tiene el puerto 8007 abierto a todo internet para recibir backups. A 100+ servidores, cada servicio de backup deberia ir por VPN privada. Reduce la superficie de ataque drasticamente.
### 4.2 DNS y service discovery
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **PowerDNS** (ya en uso) | DNS autoritativo para dominios propios. Ya desplegado en la VM 135241 como secundario. | Cualquiera |
| **CoreDNS** | DNS ligero, ideal para service discovery interno. Se integra con Consul y Kubernetes. | 50-5000+ |
| **Consul (HashiCorp)** | Service discovery + health checking + KV store. Los servicios se registran y se encuentran automaticamente. | 100-5000+ |
- No olvidar: con 100+ servidores, mantener `/etc/hosts` o DNS manual no escala. Service discovery automatico elimina errores de configuracion y permite failover automatico.
### 4.3 Proxy y balanceo
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Traefik** (ya en uso en VM) | Reverse proxy con autodiscovery Docker y Let's Encrypt automatico. Ya desplegado para los paneles DNS. | Cualquiera |
| **Nginx Proxy Manager** | Reverse proxy con UI simple. Ideal para equipos que no quieren YAML. | 10-100 |
| **HAProxy** | Balanceador de carga de alto rendimiento. Para distribuir trafico de backup entre multiples PBS. | 50-5000+ |
---
## Capa 5: Gestion de incidentes y comunicacion
### 5.1 Ticketing y alertas
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **PagerDuty / Opsgenie** | Escalado de alertas, on-call rotation, integracion con monitoring. Cuando Prometheus alerta, alguien se entera. | 50-5000+ |
| **Alertmanager (Prometheus)** | Routing de alertas: agrupar, silenciar, deduplicar. Enviar a Telegram, email, webhook, PagerDuty. | Cualquiera |
| **Zammad** | Ticketing open-source. Para que los clientes reporten problemas y el equipo los gestione con trazabilidad. | 50-1000 |
| **Mattermost** | Chat interno (alternativa a Slack). Canal de alertas, war rooms para incidentes, integracion con bots. | Cualquiera |
| **Gotify / ntfy** | Push notifications self-hosted. Para alertas criticas al movil sin depender de servicios externos. | Cualquiera |
- No olvidar: las alertas que nadie ve no sirven. El canal de alertas debe tener: niveles de severidad, escalado automatico si nadie responde en X minutos, y silenciado inteligente para evitar fatiga de alertas.
### 5.2 Documentacion operativa
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Bookstack** | Wiki self-hosted para documentacion operativa. Playbooks, runbooks, topologias de red, procedimientos. | Cualquiera |
| **Outline** | Wiki moderna con busqueda, permisos, y markdown. Alternativa a Notion self-hosted. | Cualquiera |
| **MkDocs + Material** | Documentacion como codigo. Ficheros markdown en git que generan un sitio web estatico. | Cualquiera |
- No olvidar: el CLAUDE.md de este servidor es excelente documentacion operativa. A 100+ servidores, eso deberia estar en una wiki centralizada con busqueda, no en ficheros individuales en cada servidor.
---
## Capa 6: Almacenamiento y datos
### 6.1 Gestion de ZFS a escala
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **ZFS Exporter (Prometheus)** | Metricas de pools ZFS: espacio, salud, IO, scrub status, errores. Dashboard de todos los pools en un vistazo. | Cualquiera |
| **zfswatcher** | Monitoring dedicado de ZFS con alertas por email. Detecta discos degradados, errores de checksum, scrubs fallidos. | 10-500 |
| **Sanoid / Syncoid** | Gestion automatica de snapshots ZFS y replicacion. Politicas de retencion declarativas. | Cualquiera |
| **zrepl** | Replicacion ZFS continua con push/pull. Alternativa moderna a Syncoid para replicacion entre sitios. | 10-500 |
- No olvidar: con pool9 gestionando todos los datastores de clientes, un fallo de ZFS es catastrofico. Minimo: alerta inmediata si el pool deja de estar ONLINE, alerta si un scrub encuentra errores, dashboard de ocupacion con proyeccion de cuando se llena.
### 6.2 Backup del backup
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **PBS replication (sync jobs)** | Ya en uso. Sync entre PBS servers. Pero necesita monitoring de que los syncs funcionan. | Cualquiera |
| **Restic + Minio/S3** | Backup offsite de datos criticos (configuraciones, BBDD) a object storage. Cifrado, deduplicado, barato. | Cualquiera |
| **Rclone** | Sincronizacion a cualquier cloud (S3, B2, Google, Azure). Ideal para copia offsite de backups criticos. | Cualquiera |
| **BorgBackup** | Backup deduplicado y cifrado. Alternativa a Restic. Muy maduro y fiable. | Cualquiera |
- No olvidar: el PBS tiene sync jobs mensuales desde servidores remotos. Pero quien hace backup del PBS? Si el host se pierde (ransomware, fallo hardware), se pierden todos los backups. La regla 3-2-1 aplica tambien al servidor de backups.
---
## Capa 7: Observabilidad avanzada (para +500 servidores)
### 7.1 Stack de observabilidad completo
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Grafana LGTM Stack** | Loki (logs) + Grafana (dashboards) + Tempo (traces) + Mimir (metricas). Stack unificado. | 500-10000+ |
| **Netdata** | Monitoring en tiempo real con dashboard por servidor. Muy visual, zero-config. Bueno para troubleshooting rapido. | 10-1000 |
| **Datadog / New Relic** | SaaS de observabilidad completa. Caro pero potente. Para equipos que no quieren mantener infra de monitoring. | 100-10000+ |
### 7.2 SIEM y correlacion de eventos
| Herramienta | Que resuelve | Escala |
|-------------|-------------|--------|
| **Wazuh** (repite por importancia) | SIEM + HIDS + compliance. Correlaciona eventos de multiples servidores. Detecta patrones de ataque. | 100-10000+ |
| **Security Onion** | Plataforma completa de seguridad: IDS, analisis de red, SIEM, caza de amenazas. | 100-5000 |
| **CrowdSec** | IDS colaborativo. Comparte listas de IPs maliciosas con la comunidad. Complementa Fail2ban. | Cualquiera |
---
## Priorizacion: que implementar primero
### Fase 1 - Inmediata (semana 1-2) - Supervivencia
> Detener la hemorragia y ver lo basico
1. **Wazuh** en todos los servidores (detecta intrusiones como la que encontramos)
2. **Fail2ban** en todos los servidores (ya deberia estar)
3. **Uptime Kuma** para servicios criticos (PBS, DNS, paneles)
4. **Alertas de disco** al 80% en todas las VMs y hosts
5. **Bitwarden/Vaultwarden** para el equipo (no mas contraseñas en texto plano)
### Fase 2 - Corto plazo (mes 1-2) - Fundamentos
> Visibilidad y automatizacion basica
6. **Prometheus + Grafana** con pve-exporter y ZFS exporter
7. **Grafana Loki** para logs centralizados (al menos auth.log y syslog)
8. **Netbox** para inventario de toda la infra
9. **Ansible** playbooks para hardening base (SSH, firewall, auditd)
10. **Gitea** para versionar toda la automatizacion
### Fase 3 - Medio plazo (mes 3-6) - Madurez
> Procesos y escalabilidad
11. **WireGuard/Tailscale** para trafico de backup privado
12. **Vault** para gestion de secretos
13. **Terraform** para provisionar VMs de forma reproducible
14. **Bookstack** para documentacion operativa centralizada
15. **Rundeck/AWX** para orquestacion de jobs de mantenimiento
### Fase 4 - Largo plazo (mes 6-12) - Excelencia
> Observabilidad avanzada y zero-trust
16. **Teleport** para acceso SSH centralizado con audit
17. **FreeIPA/Keycloak** para directorio central de usuarios
18. **OpenVAS** para escaneo de vulnerabilidades periodico
19. **LGTM Stack** completo si se supera los 500 servidores
20. **Security Onion** para analisis de red
---
## Resumen por necesidad
| Necesidad | Herramienta clave | Alternativa |
|-----------|------------------|-------------|
| "Me han hackeado y no me entere" | **Wazuh** | OSSEC + AIDE |
| "No se que servidores tengo" | **Netbox** | GLPI |
| "Un servicio cayo y nadie lo vio" | **Prometheus + Grafana** | Zabbix |
| "Los logs estaban solo en el servidor comprometido" | **Grafana Loki** | Graylog |
| "Contraseñas en texto plano por todos lados" | **Vault + Bitwarden** | SOPS |
| "Configuro servidores a mano y cada uno es distinto" | **Ansible** | Terraform |
| "Los backups fallan y no me entero" | **Dashboard PBS + alertas** | Script custom |
| "SSH con password abierto a internet" | **Teleport + MFA** | Fail2ban + WireGuard |
| "El disco se llena y todo cae" | **Alertas Prometheus al 80%** | Netdata |
| "No tengo documentacion de nada" | **Bookstack** | MkDocs |

160
01-decision-inventario.md Normal file
View file

@ -0,0 +1,160 @@
# Decision: Herramienta de inventario para infraestructura Proxmox/PBS
## Contexto
- 100-500 servidores Proxmox VE y PBS
- Necesidad de saber que hay, donde esta, que IP tiene, que version corre, que clientes tiene cada PBS
- Integracion con Ansible para automatizacion
---
## Opcion A: Netbox solo (CMDB pura)
**Que es**: CMDB (Configuration Management Database) open source de referencia. Diseñada por ingenieros de red de DigitalOcean.
**Que cubre**:
- Inventario de servidores fisicos (rack, U, serial, modelo)
- IPs y subredes (IPAM completo: VLANs, prefijos, rangos)
- VMs y contenedores
- Conexiones de red (que puerto fisico va a donde)
- Contactos y tenants (clientes asociados a cada recurso)
- Custom fields (quota PBS, tamaño comercial, servidor de sync, etc.)
- API REST completa (todo automatizable)
**Que NO cubre sin plugins**:
- No descubre automaticamente lo que tienes (hay que poblarlo)
- No monitoriza estado (es un inventario, no sabe si el servidor esta caido)
- No gestiona tickets ni incidencias
**Plugins clave para vuestro caso**:
- `netbox-proxmox`: sincroniza VMs, nodos y storage desde Proxmox API
- `netbox-dns`: gestion de zonas y registros DNS (complementa vuestro PowerDNS)
- `netbox-inventory`: seguimiento de activos fisicos con ciclo de vida
**Como se pobla**:
- Manual al principio (servidores fisicos, racks)
- Automatico via API + scripts que lean de Proxmox y PBS
- Ansible como consumidor: `netbox.netbox.nb_inventory` genera inventario dinamico
**Ideal si**: quereis una fuente de verdad unica, bien estructurada, que alimente al resto de herramientas (Ansible, Prometheus, Grafana). El equipo tiene disciplina para mantenerla actualizada.
**Recursos**: 2GB RAM, 1 vCPU, PostgreSQL + Redis. Una VM pequeña.
**Veredicto**: Para vuestro caso, **Netbox solo es suficiente** como inventario si le añadis el plugin de Proxmox y lo conectais con Ansible. Es la opcion mas limpia.
---
## Opcion B: GLPI + FusionInventory (inventario + autodiscovery + ticketing)
**Que es**: Gestion de activos IT + helpdesk + autodescubrimiento. Muy extendido en entornos ITIL.
**Que cubre**:
- Todo lo de inventario (servidores, VMs, IPs, software instalado)
- Autodescubrimiento: instala un agente en cada servidor y reporta automaticamente hardware, software, paquetes, actualizaciones
- Ticketing integrado (incidencias, peticiones, cambios)
- Gestion de contratos y proveedores (util para controlar hosting OVH, licencias)
- Base de conocimiento (wiki interna)
- SLA tracking
**Que NO cubre**:
- IPAM menos potente que Netbox
- No tiene concepto nativo de "tenant/cliente" tan limpio como Netbox
- Integracion con Ansible menos directa (existe pero no es nativa)
**Ventaja diferencial**: el agente FusionInventory escanea automaticamente cada servidor y reporta: hardware, paquetes instalados, versiones, discos, red. No tienes que mantener el inventario a mano, se actualiza solo.
**Ideal si**: quereis que el inventario se mantenga solo (autodiscovery), necesitais ticketing integrado, y el equipo prefiere una herramienta "todo en uno" tipo helpdesk.
**Recursos**: 2GB RAM, 1 vCPU, MariaDB + Apache. Una VM pequeña.
**Veredicto**: Mas facil de mantener actualizado que Netbox (autodiscovery), pero menos potente como CMDB de red y menos integracion con ecosistema DevOps.
---
## Opcion C: Netbox + Ansible inventory + Prometheus service discovery (stack integrado)
**Que es**: No es una herramienta sino un patron. Netbox como SSOT, Ansible como consumidor y actualizador, Prometheus como validador.
**Flujo**:
```
Netbox (SSOT) --> Ansible (dynamic inventory) --> Configura servidores
^ |
| v
+---- Script sync <-- Proxmox API (autodescubre VMs nuevas)
|
+---- Prometheus (valida que lo que dice Netbox coincide con la realidad)
```
**Componentes**:
1. **Netbox**: inventario maestro con plugin proxmox
2. **Script de sync** (cron diario): consulta la API de cada Proxmox, crea/actualiza VMs en Netbox automaticamente
3. **Ansible `netbox.netbox.nb_inventory`**: genera inventario dinamico desde Netbox. Los playbooks siempre trabajan contra datos reales.
4. **Prometheus + netbox-prometheus-sd**: Prometheus descubre targets desde Netbox. Si un servidor esta en Netbox, se monitoriza automaticamente.
**Que cubre**:
- Todo lo de Netbox (Opcion A)
- Autodescubrimiento via API de Proxmox (no necesita agente como GLPI)
- Inventario siempre sincronizado con la realidad
- Monitoring automatico de todo lo que entra en inventario
- Ansible siempre trabaja con datos actualizados
**Que requiere**:
- Mas trabajo inicial de integracion (scripts de sync, configurar plugins)
- El equipo tiene que entender el flujo completo
- Necesita Prometheus y Grafana (que ya deberian desplegarse de todos modos)
**Ideal si**: quereis construir un ecosistema integrado donde añadir un servidor a Netbox automaticamente lo provisione con Ansible y lo monitorice con Prometheus. La opcion mas potente a largo plazo.
**Recursos**: Netbox VM (2GB) + Prometheus/Grafana (ya necesario para monitoring).
**Veredicto**: Mas esfuerzo inicial, pero es el objetivo final al que llegareis con cualquiera de las otras opciones. Si vais a desplegar Prometheus y Ansible de todos modos, tiene sentido empezar con este enfoque.
---
## Comparativa rapida
| Criterio | A: Netbox solo | B: GLPI+Fusion | C: Netbox+stack |
|----------|---------------|----------------|-----------------|
| Esfuerzo inicial | Medio | Bajo | Alto |
| Mantenimiento | Manual + API | Automatico (agente) | Automatico (API) |
| IPAM (gestion IPs) | Excelente | Basico | Excelente |
| Autodiscovery | Con plugin/script | Nativo (agente) | Con script |
| Ticketing | No (necesita otra tool) | Integrado | No |
| Integracion Ansible | Nativa | Plugin | Nativa |
| Integracion Prometheus | Plugin | No directa | Nativa |
| Tenants/clientes | Excelente | Basico | Excelente |
| Curva de aprendizaje | Media | Baja | Alta |
| Comunidad Proxmox | Fuerte | Media | Fuerte |
| Escalabilidad | 10000+ | 5000 | 10000+ |
---
## Mi recomendacion para vuestro caso
**Opcion C**, pero implementada en fases:
1. **Semana 1-2**: Desplegar Netbox con plugin proxmox. Importar servidores fisicos y que sincronice VMs automaticamente.
2. **Semana 3-4**: Conectar Ansible con inventario dinamico de Netbox. Primer playbook de hardening base.
3. **Mes 2**: Añadir script de sync PBS (datastores, clientes, quotas como custom fields en Netbox).
4. **Mes 2-3**: Conectar Prometheus con Netbox para service discovery automatico.
Resultado: cualquier servidor nuevo que se añada a Proxmox aparece en Netbox automaticamente, se configura con Ansible, y se monitoriza con Prometheus. Sin intervencion manual.
---
## Nota sobre datos especificos de PBS que modelar en Netbox
Custom fields recomendados para vuestro modelo de negocio:
| Campo | Tipo | Ejemplo |
|-------|------|---------|
| `pbs_commercial_size_gb` | Integer | 100 |
| `pbs_quota_gb` | Integer | 600 |
| `pbs_reservation_gb` | Integer | 500 |
| `pbs_sync_server` | Text | pbs3343.vpn9.com.es |
| `pbs_sync_day` | Integer | 15 |
| `pbs_password` | Secret (via Vault) | - |
| `pbs_pve_host` | Text | ns31157129.ip-51-91-154.eu |
| `pbs_status` | Choice | active / migrated / suspended |
| `pbs_last_gc` | DateTime | auto-updated |
| `pbs_last_verify` | DateTime | auto-updated |
| `pbs_used_space_gb` | Integer | auto-updated |

295
02-decision-monitoring.md Normal file
View file

@ -0,0 +1,295 @@
# Decision: Stack de monitoring para infraestructura Proxmox/PBS (100-500 servidores)
## Descartados y por que
| Herramienta | Motivo de descarte |
|-------------|-------------------|
| **Checkmk** | Probado en produccion. Nagios por debajo, consumo de recursos excesivo, version open source limitada. Descartado por experiencia directa. |
| **Nagios/Icinga** | Misma generacion que Checkmk. Modelo de plugins obsoleto. No merece la pena en 2026. |
| **Datadog/New Relic** | SaaS. A 100-500 servidores el coste mensual es prohibitivo y dependes de terceros para tu infra critica. |
---
## La pregunta clave: Prometheus vs VictoriaMetrics
No son competidores exactos. VictoriaMetrics es la **evolucion** de Prometheus:
| Aspecto | Prometheus | VictoriaMetrics |
|---------|-----------|-----------------|
| Lenguaje de consulta | PromQL | MetricsQL (superset de PromQL, compatible) |
| Consumo de RAM | Alto (todo en memoria) | 5-10x menos RAM |
| Consumo de disco | Alto (TSDB poco eficiente) | 7-10x menos disco (compresion agresiva) |
| Retencion largo plazo | Problematico (necesita Thanos/Cortex) | Nativo, sin componentes extra |
| Alta disponibilidad | Necesita Thanos o Cortex | Nativo en cluster mode |
| Compatibilidad | Es el estandar | 100% compatible (scrape, exporters, Grafana, Alertmanager) |
| Scraping | Integrado | vmagent (separado, mas eficiente) |
| Alertas | Alertmanager (separado) | vmalert (integrado) O Alertmanager (compatible) |
| Escalabilidad | Un Prometheus por ~500 targets | Un VictoriaMetrics para miles de targets |
| Complejidad | Simple a escala pequeña | Simple a cualquier escala |
### Recomendacion: **VictoriaMetrics** (single-node)
A 100-500 servidores, un solo nodo de VictoriaMetrics gestiona todo sin problemas. Si algun dia pasais de 1000, se escala a cluster sin cambiar nada mas.
Toda la comunidad de exporters de Prometheus funciona tal cual. Grafana se conecta igual. Los dashboards existentes de Proxmox/ZFS funcionan sin cambiar nada.
---
## Stack propuesto: 4 capas
```
┌─────────────────────────────┐
│ GRAFANA │
│ Dashboards + Alertas UI │
└──────────┬──────────────────┘
│ consulta
┌──────────▼──────────────────┐
│ VICTORIA METRICS │
│ Almacen de metricas │
│ (retencion 1 año+) │
└──────────┬──────────────────┘
│ recibe
┌──────────▼──────────────────┐
│ VMAGENT │
│ Scraping de todos los │
│ exporters (reemplaza │
│ Prometheus server) │
└──────────┬──────────────────┘
│ scrape
┌────────────────────┼────────────────────┐
│ │ │
┌──────▼──────┐ ┌───────▼───────┐ ┌───────▼───────┐
│ node_exporter│ │ pve_exporter │ │ pbs-exporter │
│ (cada server)│ │ (cada PVE) │ │ (natrontech) │
│ │ │ │ │ multi-target │
│ CPU, RAM, │ │ VMs, nodos, │ │ datastores, │
│ disco, red, │ │ storage, │ │ snapshots/VM, │
│ ZFS pools │ │ cluster │ │ ultimo backup,│
│ │ │ │ │ + script jobs │
│ │ │ │ │ (GC/verify/ │
│ │ │ │ │ sync) │
└──────────────┘ └───────────────┘ └───────────────┘
+ Uptime Kuma (aparte, para checks binarios de disponibilidad)
```
---
## Capa 1: Recoleccion (exporters en cada servidor)
### node_exporter (obligatorio en todos los servidores)
- Metricas de sistema: CPU, RAM, disco, red, load, filesystem
- Incluye metricas de ZFS automaticamente (pool health, space, IO, ARC)
- 5MB de RAM, impacto nulo en rendimiento
- Despliegue: un playbook de Ansible, 2 minutos por servidor
### pve_exporter (uno por cluster Proxmox)
- Metricas de la API de Proxmox: estado de VMs, nodos, storage, replicacion
- No necesita instalarse en cada nodo, consulta la API del cluster
- Una instancia por cluster PVE
### pbs-exporter (natrontech) - centralizado, multi-target
- Exporter comunitario en Go: https://github.com/natrontech/pbs-exporter
- **Modo multi-target**: una sola instancia para N servidores PBS (no instalar en cada PBS)
- Cubre: datastores (espacio), snapshots por VM, ultimo backup por VM, host metrics
- Complementado con script de ~40 lineas via textfile collector para GC/verify/sync jobs
- Detalle completo en `decision-monitoring-pbs.md`
- Un unico backend: VictoriaMetrics. Sin InfluxDB.
---
## Capa 2: Almacenamiento (VictoriaMetrics)
### Despliegue single-node
- Una VM con 2-4 vCPU, 4-8GB RAM, 100-200GB disco
- Retencion de 1 año de metricas con compresion agresiva
- Parametros clave:
- `-retentionPeriod=12m` (12 meses)
- `-storageDataPath=/data/victoria-metrics`
- `-httpListenAddr=:8428`
- Recibe metricas de vmagent via remote_write
- Compatible con todas las consultas PromQL/MetricsQL de Grafana
### vmagent (scraper)
- Reemplaza al Prometheus server para la funcion de scraping
- Configuracion identica a Prometheus (mismo YAML de scrape_configs)
- Descubrimiento de targets: desde Netbox (via HTTP SD) o fichero estatico
- Envia todo a VictoriaMetrics via remote_write
- Puede correr en la misma VM o separado
---
## Capa 3: Alertas (vmalert + Alertmanager)
### vmalert
- Evalua reglas de alerta contra VictoriaMetrics
- Misma sintaxis de reglas que Prometheus alerting rules
- Envia a Alertmanager para routing y notificacion
### Alertmanager
- Routing: que alerta va a quien
- Agrupacion: no enviar 100 alertas individuales si hay un fallo general
- Silenciado: mantenimientos programados sin spam de alertas
- Integraciones de notificacion:
- **Telegram** (recomendado para alertas criticas, llega al movil)
- **Email** (para alertas informativas)
- **Webhook** (para integrar con ICSManager, Mattermost, etc.)
### Alertas minimas obligatorias
```yaml
# DISCO
- alert: DiskSpaceWarning
expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) < 0.20
for: 10m
labels: { severity: warning }
annotations: { summary: "Menos del 20% libre en {{ $labels.instance }}" }
- alert: DiskSpaceCritical
expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) < 0.10
for: 5m
labels: { severity: critical }
# ZFS
- alert: ZFSPoolDegraded
expr: node_zfs_zpool_state{state!="online"} > 0
for: 1m
labels: { severity: critical }
annotations: { summary: "ZFS pool degradado en {{ $labels.instance }}" }
- alert: ZFSPoolSpaceHigh
expr: (node_zfs_zpool_allocated / node_zfs_zpool_size) > 0.85
for: 30m
labels: { severity: warning }
# PBS
- alert: PBSDatastoreNoBackup48h
expr: (time() - pbs_datastore_last_backup_timestamp) > 172800
for: 1h
labels: { severity: critical }
annotations: { summary: "Sin backup en 48h: {{ $labels.datastore }}" }
- alert: PBSGCNotRunning
expr: (time() - pbs_gc_last_run_timestamp) > 259200
for: 1h
labels: { severity: warning }
annotations: { summary: "GC no ejecutado en 3 dias: {{ $labels.datastore }}" }
- alert: PBSVerifyErrors
expr: pbs_verify_errors_total > 0
for: 5m
labels: { severity: warning }
- alert: PBSDatastoreQuota90
expr: (pbs_datastore_used_bytes / pbs_datastore_quota_bytes) > 0.90
for: 30m
labels: { severity: warning }
# NODO
- alert: NodeDown
expr: up == 0
for: 3m
labels: { severity: critical }
- alert: HighCPU
expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
for: 15m
labels: { severity: warning }
- alert: HighMemory
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) > 0.90
for: 10m
labels: { severity: warning }
# SEGURIDAD (basado en lo aprendido)
- alert: SuspiciousFileChange
expr: node_textfile_mtime_seconds{file="pam_integrity"} != node_textfile_mtime_seconds{file="pam_integrity"} offset 5m
for: 1m
labels: { severity: critical }
annotations: { summary: "Cambio detectado en ficheros PAM en {{ $labels.instance }}" }
```
---
## Capa 4: Visualizacion (Grafana)
### Dashboards recomendados
| Dashboard | Fuente | Uso |
|-----------|--------|-----|
| **Panorama general** | VictoriaMetrics | Mapa de todos los servidores, estado global, alertas activas |
| **Nodo Proxmox** | pve_exporter | VMs corriendo, CPU/RAM/storage por nodo, estado del cluster |
| **ZFS por pool** | node_exporter | Espacio, health, scrub status, IO, ARC hit rate |
| **PBS por servidor** | pbs-exporter (natrontech) + script jobs | Datastores, ocupacion vs quota, jobs GC/verify/sync |
| **Cliente individual** | Custom exporter | Vista para un cliente: espacio usado, ultimo backup, tendencia de crecimiento |
| **Capacidad global** | VictoriaMetrics | Tendencias de crecimiento, prediccion de cuando se llena cada pool, planificacion de compras |
### Grafana alerting (alternativa simple a vmalert)
- Grafana 10+ tiene alerting integrado potente
- Si no quereis gestionar vmalert + Alertmanager por separado, Grafana puede evaluar alertas directamente y enviar a Telegram/email
- Mas simple, menos potente en routing, pero suficiente para empezar
---
## Uptime Kuma: donde encaja
Uptime Kuma NO reemplaza al stack de metricas. Es complementario:
| Stack metricas (VictoriaMetrics) | Uptime Kuma |
|----------------------------------|-------------|
| Metricas continuas (CPU al 73.4%) | Vivo o muerto (si/no) |
| Alertas por umbral (disco > 80%) | Alerta si no responde |
| Historico de rendimiento | Historico de disponibilidad (uptime %) |
| Requiere exporter en cada servidor | No requiere nada en el servidor |
| Complejo | Muy simple, 5 minutos |
**Donde usar Uptime Kuma**:
- Check externo de que PBS:8007 responde desde fuera
- Check de que el DNS (VM 135241) resuelve correctamente
- Check de que los paneles web (Proxmox GUI, PowerDNS Admin) estan accesibles
- Check de certificados SSL (avisa X dias antes de expirar)
- Pagina de status publica para clientes (opcional)
**Donde NO usar Uptime Kuma**:
- Para metricas de rendimiento (eso es VictoriaMetrics)
- Para alertas de disco/ZFS/jobs (eso es vmalert/Grafana)
- Como monitoring principal (es complementario)
---
## Zabbix: por que no lo recomiendo para vuestro caso
Zabbix es muy bueno, pero:
| Zabbix | Stack propuesto |
|--------|----------------|
| Todo en uno (metricas + alertas + dashboards + discovery) | Componentes separados especializados |
| UI propia (potente pero anticuada) | Grafana (moderna, extensible, estandar) |
| Lenguaje de templates propio | PromQL/MetricsQL (estandar de la industria) |
| Agente propio | Exporters de Prometheus (ecosistema enorme) |
| Base de datos relacional (PostgreSQL/MySQL) | TSDB optimizada (VictoriaMetrics) |
| Comunidad Proxmox: templates disponibles | Comunidad Proxmox: exporters maduros |
| Bueno si ya lo conoces | Mejor inversion de aprendizaje a futuro |
Zabbix funciona bien si el equipo ya lo domina. Si estais empezando de cero, invertir en aprender el ecosistema Prometheus/VictoriaMetrics os da mas flexibilidad y es el estandar hacia el que se mueve toda la industria.
Si el equipo no tiene experiencia con ninguno y quiere algo rapido, Zabbix es mas facil de poner a funcionar el primer dia. Pero a medio plazo, el stack propuesto es mas potente y consume menos recursos.
---
## Resumen del punto 1.2 revisado
| Componente | Herramienta | Funcion |
|-----------|-------------|---------|
| **Metricas** | VictoriaMetrics (single-node) | Almacen de todas las metricas, retencion 1 año |
| **Scraping** | vmagent | Recolecta de todos los exporters |
| **Exporters** | node_exporter + pve_exporter + pbs-exporter (natrontech) + script jobs | Generan metricas en cada servidor |
| **Alertas** | Grafana alerting (fase 1) o vmalert + Alertmanager (fase 2) | Notificaciones Telegram/email |
| **Dashboards** | Grafana | Visualizacion de todo |
| **Disponibilidad** | Uptime Kuma | Checks binarios externos (vivo/muerto) |
### Recursos totales estimados
- VM VictoriaMetrics + vmagent + Grafana: 4 vCPU, 8GB RAM, 200GB disco
- VM Uptime Kuma: 1 vCPU, 512MB RAM, 10GB disco (o contenedor Docker en VM existente)
- node_exporter por servidor: 5MB RAM, impacto nulo
- pve_exporter por cluster: 50MB RAM

View file

@ -0,0 +1,492 @@
# Decision: Monitoring especifico de PBS (punto 1.3)
## El problema
PBS no tiene exporter Prometheus nativo. Las metricas hay que extraerlas de alguna forma.
Evaluamos 3 vias para alimentar VictoriaMetrics/Grafana con datos de PBS.
---
## Via A: PBS metricas nativas a InfluxDB
### Que es
PBS tiene soporte nativo para enviar metricas a InfluxDB. Se configura desde la GUI o CLI sin instalar nada en el PBS.
### Como funciona
```
PBS ----(push nativo)----> InfluxDB ----(datasource)----> Grafana
^
VictoriaMetrics ---------(datasource)---------------------+
```
Grafana lee de dos backends: VictoriaMetrics (infra) e InfluxDB (PBS).
### Configuracion
```bash
# En cada PBS, añadir metric server
proxmox-backup-manager metric-server add influxdb mi-influxdb \
--server <ip-influxdb> \
--port 8089 \
--protocol udp
```
### Metricas que envia PBS nativamente
- Uso de CPU, RAM, IO del host PBS
- Espacio total/usado/disponible por datastore
- Estado de GC (running, last-run)
- Trafico de red
- Estadisticas de chunks (deduplication ratio)
### Lo que NO envia nativamente
- Estado de sync jobs (exito/fallo, ultimo run, bytes transferidos)
- Estado de verify jobs (errores encontrados, ultimo run)
- Ultimo backup por datastore/cliente
- Quota vs uso real por cliente
- Lista de snapshots y su antiguedad
- Estado de maintenance mode
### Veredicto
**Insuficiente como solucion unica.** Util como complemento rapido para metricas basicas de espacio, pero no cubre lo operacionalmente critico.
---
## Via B: natrontech/pbs-exporter + script complementario (RECOMENDADA)
### Que es
Combinacion de un exporter comunitario maduro en Go (`natrontech/pbs-exporter`) que cubre datastores, snapshots y host, complementado con un script ligero via textfile collector para las metricas de jobs (GC, verify, sync) que el exporter no cubre.
### pbs-exporter (natrontech)
**Repositorio**: https://github.com/natrontech/pbs-exporter
**Lenguaje**: Go | **Licencia**: GPL-3.0 | **Version**: v0.8.0 (dic 2025) | **Stars**: 45
**Testado con**: PBS 3.x
#### Metricas que expone
```prometheus
# === SISTEMA PBS ===
pbs_up # 1 si PBS responde, 0 si no
pbs_version{version="3.3-1"} # Version de PBS
# === ALMACENAMIENTO POR DATASTORE ===
pbs_available{datastore="cliente1"} # Bytes disponibles
pbs_size{datastore="cliente1"} # Bytes totales
pbs_used{datastore="cliente1"} # Bytes usados
# === SNAPSHOTS ===
pbs_snapshot_count{datastore="cliente1"} # Total snapshots
pbs_snapshot_vm_count{id="101",datastore=".."} # Snapshots por VM
pbs_snapshot_vm_last_timestamp{id="101",...} # Timestamp ultimo backup por VM
pbs_snapshot_vm_last_verify{id="101",...} # Estado verificacion ultimo backup
# === HOST ===
pbs_host_cpu_usage # Uso CPU
pbs_host_memory_free / _total / _used # RAM
pbs_host_swap_free / _total / _used # Swap
pbs_host_disk_available / _total / _used # Disco
pbs_host_uptime # Uptime en segundos
pbs_host_io_wait # IO wait
pbs_host_load1 / _load5 / _load15 # Load averages
# === SUSCRIPCION ===
pbs_host_subscription_status # Estado licencia
pbs_host_subscription_due_timestamp_seconds # Expiracion
```
#### Modo multi-target (clave para escalar)
Un solo pbs-exporter puede monitorizar multiples PBS:
```yaml
# vmagent scrape config
- job_name: 'pbs'
metrics_path: /metrics
params:
module: [default]
static_configs:
- targets:
- https://pbs-server1:8007
- https://pbs-server2:8007
- https://pbs-server3:8007
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: pbs-exporter:10019 # un solo exporter central
```
Esto significa: **1 instancia de pbs-exporter para N servidores PBS**. No hay que instalar nada en cada PBS.
#### Despliegue
**Opcion 1: Docker (recomendado para centralizacion)**
```yaml
services:
pbs-exporter:
image: ghcr.io/natrontech/pbs-exporter:latest
container_name: pbs-exporter
restart: unless-stopped
environment:
- PBS_API_TOKEN_NAME=pbs-exporter
- PBS_API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- PBS_USERNAME=monitoring@pbs
- PBS_INSECURE=true
ports:
- "10019:10019"
```
**Opcion 2: Binario + systemd (en cada PBS si no se usa multi-target)**
```bash
# Crear usuario dedicado en PBS (minimos privilegios)
proxmox-backup-manager user create monitoring@pbs
proxmox-backup-manager user generate-token monitoring@pbs pbs-exporter
# Dar solo permisos Audit
proxmox-backup-manager acl update / Audit --auth-id monitoring@pbs
# Descargar binario
wget https://github.com/natrontech/pbs-exporter/releases/download/v0.8.0/pbs-exporter_linux_amd64
chmod +x pbs-exporter_linux_amd64
mv pbs-exporter_linux_amd64 /usr/local/bin/pbs-exporter
# Systemd unit
cat > /etc/systemd/system/pbs-exporter.service << 'EOF'
[Unit]
Description=PBS Prometheus Exporter
After=network.target proxmox-backup.service
[Service]
Type=simple
EnvironmentFile=/etc/default/pbs-exporter
ExecStart=/usr/local/bin/pbs-exporter
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Configuracion
cat > /etc/default/pbs-exporter << 'EOF'
PBS_API_TOKEN_NAME=pbs-exporter
PBS_API_TOKEN=<token-generado>
PBS_USERNAME=monitoring@pbs
PBS_ENDPOINT=https://localhost:8007
PBS_INSECURE=true
PBS_LISTEN_ADDRESS=:10019
EOF
systemctl enable --now pbs-exporter
```
#### Lo que NO cubre pbs-exporter
- Estado de GC jobs (ultimo run, duracion, espacio liberado)
- Estado de sync jobs (exito/fallo, ultimo run, bytes, remote)
- Estado de verify jobs (como job programado, no como verificacion de snapshot)
- Maintenance mode
- Quota/reservation ZFS por datastore
### Script complementario para jobs (textfile collector)
Solo cubre lo que pbs-exporter no tiene. ~40 lineas.
```bash
#!/bin/bash
# /usr/local/sbin/pbs-jobs-metrics.sh
# Complementa pbs-exporter con metricas de GC, verify y sync jobs
# Cron: */10 * * * * /usr/local/sbin/pbs-jobs-metrics.sh
OUTPUT="/var/lib/node_exporter/textfile/pbs_jobs.prom"
TMPFILE="${OUTPUT}.tmp"
PBS_API="https://localhost:8007/api2/json"
# Autenticacion con API token (sin password)
TOKEN_NAME="monitoring@pbs!pbs-exporter"
TOKEN_VALUE="<mismo-token-que-pbs-exporter>"
AUTH_HEADER="Authorization: PBSAPIToken=${TOKEN_NAME}:${TOKEN_VALUE}"
api_get() {
curl -sk -H "$AUTH_HEADER" "${PBS_API}${1}"
}
> "$TMPFILE"
# GC jobs
api_get "/admin/gc" | jq -r '.data[] | @base64' | while read row; do
_jq() { echo "$row" | base64 -d | jq -r "$1 // 0"; }
store=$(_jq '.store')
last=$(_jq '."last-run-endtime"')
state=$(_jq '."last-run-state"')
ok=0; [ "$state" = "ok" ] && ok=1
echo "pbs_gc_last_run_timestamp{datastore=\"${store}\"} ${last}" >> "$TMPFILE"
echo "pbs_gc_last_status{datastore=\"${store}\"} ${ok}" >> "$TMPFILE"
done
# Verify jobs
api_get "/admin/verify" | jq -r '.data[] | @base64' | while read row; do
_jq() { echo "$row" | base64 -d | jq -r "$1 // 0"; }
store=$(_jq '.store')
last=$(_jq '."last-run-endtime"')
state=$(_jq '."last-run-state"')
ok=0; [ "$state" = "ok" ] && ok=1
echo "pbs_verify_last_run_timestamp{datastore=\"${store}\"} ${last}" >> "$TMPFILE"
echo "pbs_verify_last_status{datastore=\"${store}\"} ${ok}" >> "$TMPFILE"
done
# Sync jobs
api_get "/admin/sync" | jq -r '.data[] | @base64' | while read row; do
_jq() { echo "$row" | base64 -d | jq -r "$1 // 0"; }
store=$(_jq '.store')
remote=$(_jq '.remote')
last=$(_jq '."last-run-endtime"')
state=$(_jq '."last-run-state"')
ok=0; [ "$state" = "ok" ] && ok=1
echo "pbs_sync_last_run_timestamp{datastore=\"${store}\",remote=\"${remote}\"} ${last}" >> "$TMPFILE"
echo "pbs_sync_last_status{datastore=\"${store}\",remote=\"${remote}\"} ${ok}" >> "$TMPFILE"
done
mv "$TMPFILE" "$OUTPUT"
```
### Arquitectura resultante
```
vmagent scrape
├── :9100 node_exporter (sistema + ZFS quotas)
│ └── textfile/pbs_jobs.prom (GC/verify/sync jobs via script)
└── :10019 pbs-exporter (datastores, snapshots, ultimo backup por VM, host)
└── multi-target: puede cubrir N servidores PBS
```
**Un unico backend**: VictoriaMetrics. Sin InfluxDB. Todo en PromQL/MetricsQL.
### Ventajas de esta combinacion
- pbs-exporter hace el 80% del trabajo pesado (datastores, snapshots por VM, host)
- Script de 40 lineas cubre el 20% restante (jobs)
- Mismo token de API para ambos (un solo usuario `monitoring@pbs`)
- Multi-target: un pbs-exporter central para todos los PBS
- Si el exporter crece y añade metricas de jobs en el futuro, se elimina el script
### Desventajas
- Dos fuentes de metricas PBS (exporter + textfile), pero ambas en el mismo backend
- El script tiene resolucion de cron (10 min), el exporter es real-time
- Depende de un proyecto comunitario (45 stars, pero activo y en Go)
---
## Via C: Script completo custom (textfile collector) - DESCARTADA como principal
La Via B original del documento anterior. Sigue siendo valida como fallback si pbs-exporter deja de mantenerse o tiene algun problema, pero no tiene sentido reescribir en bash lo que ya existe en Go con mejor rendimiento y multi-target.
Se mantiene el script completo en la seccion de referencia por si fuera necesario en el futuro.
<details>
<summary>Script completo de referencia (click para expandir)</summary>
```bash
#!/bin/bash
# /usr/local/sbin/pbs-metrics-exporter.sh
# Version completa: genera TODAS las metricas PBS
# Solo usar si pbs-exporter de natrontech no esta disponible
OUTPUT="/var/lib/node_exporter/textfile/pbs_metrics.prom"
TMPFILE="${OUTPUT}.tmp"
PBS_API="https://localhost:8007/api2/json"
PBS_USER="root@pam"
PBS_PASS="$(cat /etc/pbs-monitoring-password)"
TICKET_DATA=$(curl -sk -d "username=${PBS_USER}&password=${PBS_PASS}" \
"${PBS_API}/access/ticket")
TICKET=$(echo "$TICKET_DATA" | jq -r '.data.ticket')
CSRF=$(echo "$TICKET_DATA" | jq -r '.data.CSRFPreventionToken')
api_get() {
curl -sk -b "PBSAuthCookie=${TICKET}" -H "CSRFPreventionToken: ${CSRF}" \
"${PBS_API}${1}"
}
> "$TMPFILE"
# Datastore usage
api_get "/status/datastore-usage" | jq -r '.data[] | @base64' | while read row; do
_jq() { echo "$row" | base64 -d | jq -r "$1 // 0"; }
name=$(_jq '.store')
echo "pbs_datastore_size_bytes{datastore=\"${name}\"} $(_jq '.total')" >> "$TMPFILE"
echo "pbs_datastore_used_bytes{datastore=\"${name}\"} $(_jq '.used')" >> "$TMPFILE"
echo "pbs_datastore_available_bytes{datastore=\"${name}\"} $(_jq '.avail')" >> "$TMPFILE"
done
# GC jobs
api_get "/admin/gc" | jq -r '.data[] | @base64' | while read row; do
_jq() { echo "$row" | base64 -d | jq -r "$1 // 0"; }
store=$(_jq '.store'); last=$(_jq '."last-run-endtime"')
state=$(_jq '."last-run-state"'); ok=0; [ "$state" = "ok" ] && ok=1
echo "pbs_gc_last_run_timestamp{datastore=\"${store}\"} ${last}" >> "$TMPFILE"
echo "pbs_gc_last_status{datastore=\"${store}\"} ${ok}" >> "$TMPFILE"
done
# Verify jobs
api_get "/admin/verify" | jq -r '.data[] | @base64' | while read row; do
_jq() { echo "$row" | base64 -d | jq -r "$1 // 0"; }
store=$(_jq '.store'); last=$(_jq '."last-run-endtime"')
state=$(_jq '."last-run-state"'); ok=0; [ "$state" = "ok" ] && ok=1
echo "pbs_verify_last_run_timestamp{datastore=\"${store}\"} ${last}" >> "$TMPFILE"
echo "pbs_verify_last_status{datastore=\"${store}\"} ${ok}" >> "$TMPFILE"
done
# Sync jobs
api_get "/admin/sync" | jq -r '.data[] | @base64' | while read row; do
_jq() { echo "$row" | base64 -d | jq -r "$1 // 0"; }
store=$(_jq '.store'); remote=$(_jq '.remote')
last=$(_jq '."last-run-endtime"')
state=$(_jq '."last-run-state"'); ok=0; [ "$state" = "ok" ] && ok=1
echo "pbs_sync_last_run_timestamp{datastore=\"${store}\",remote=\"${remote}\"} ${last}" >> "$TMPFILE"
echo "pbs_sync_last_status{datastore=\"${store}\",remote=\"${remote}\"} ${ok}" >> "$TMPFILE"
done
mv "$TMPFILE" "$OUTPUT"
```
</details>
---
## Comparativa final actualizada
| Aspecto | A: InfluxDB nativo | B: pbs-exporter + script (RECOMENDADA) | C: Script completo custom |
|---------|-------------------|---------------------------------------|--------------------------|
| Esfuerzo de setup | 5 minutos | 30 min exporter + 1h script | 2 horas |
| Datastores (espacio) | Si | Si (exporter) | Si |
| Snapshots por VM | No | Si (exporter) | Posible (mas script) |
| Ultimo backup por VM | No | Si (exporter) | Posible (mas script) |
| GC jobs | Basico | Si (script) | Si |
| Verify jobs | No | Si (script) | Si |
| Sync jobs | No | Si (script) | Si |
| Host metrics | Si | Si (exporter) | Manual |
| Multi-target (1 instancia para N PBS) | N/A | Si (exporter) | No |
| Backend | InfluxDB (extra) | VictoriaMetrics (unificado) | VictoriaMetrics (unificado) |
| Dependencias | InfluxDB | Binario Go + bash/curl/jq | bash/curl/jq |
| Resolucion | ~30s | Real-time (exporter) + 10min (script) | 5-15 min |
| Mantenimiento | Nulo | Bajo | Medio |
| Alertas PromQL | No | Si | Si |
---
## Recomendacion final
### Despliegue en fases
**Fase 1 (dia 1): pbs-exporter centralizado**
1. Crear usuario `monitoring@pbs` + API token en cada PBS (Ansible playbook)
2. Desplegar un pbs-exporter en Docker (VM de monitoring) en modo multi-target
3. Configurar vmagent para scrapear todos los PBS via multi-target
4. Dashboard Grafana basico: datastores, espacio, ultimo backup por VM
**Fase 2 (dia 2-3): script complementario de jobs**
1. Desplegar `pbs-jobs-metrics.sh` en cada PBS via Ansible
2. Configurar cron cada 10 minutos
3. node_exporter ya esta instalado (del punto 1.2), solo añadir textfile path
4. Dashboard Grafana: añadir paneles de GC, verify, sync jobs
**Fase 3 (semana 2): alertas**
1. Configurar alertas en Grafana o vmalert:
- `pbs_snapshot_vm_last_timestamp` > 48h sin backup
- `pbs_gc_last_status` != 1
- `pbs_verify_last_status` != 1
- `pbs_sync_last_status` != 1
- `pbs_used / pbs_size` > 0.90
2. Notificaciones: Telegram para criticas, email para warnings
**Fase 4 (mes 2): capacity planning**
1. Dashboard de tendencias de crecimiento por datastore
2. Prediccion de llenado con `predict_linear()` de PromQL
3. Deteccion de quotas sobredimensionadas
---
## Dashboards PBS para Grafana
### Dashboard 1: Vista global PBS (para el NOC / pantalla grande)
```
┌─────────────────────────────────────────────────────────┐
│ PBS GLOBAL STATUS │
├──────────────┬──────────────┬──────────────┬────────────┤
│ Datastores │ Espacio │ Jobs OK │ Alertas │
│ 42 │ 78% usado │ 39/42 │ 3 │
├──────────────┴──────────────┴──────────────┴────────────┤
│ │
│ [Tabla] Datastores con problemas │
│ - cliente7: verify fallido hace 5 dias │
│ - cliente12: sync fallido, ultimo ok hace 45 dias │
│ - cliente23: espacio > 90% quota │
│ │
├──────────────────────────────────────────────────────────┤
│ [Barras] Top 10 datastores por ocupacion │
│ ████████████████████░░░░ cliente3 82% │
│ ███████████████████░░░░░ cliente1 78% │
│ ... │
├──────────────────────────────────────────────────────────┤
│ [Timeline] Jobs ejecutados hoy │
│ 09:00 GC cliente1 OK (12min) │
│ 09:30 GC cliente2 OK (8min) │
│ 10:00 Verify cliente5 OK (45min) │
│ 10:30 Verify cliente8 FAIL (errors: 2) │
└──────────────────────────────────────────────────────────┘
```
### Dashboard 2: Detalle por datastore (para operaciones)
```
┌─────────────────────────────────────────────────────────┐
│ DATASTORE: cliente1 Status: ACTIVE │
├──────────────┬──────────────┬──────────────┬────────────┤
│ Espacio │ Quota │ Dedup ratio │ Snapshots │
│ 322 GB │ 600 GB │ 1.42x │ 45 │
├──────────────┴──────────────┴──────────────┴────────────┤
│ [Grafico linea] Espacio usado ultimos 90 dias │
│ (tendencia de crecimiento + prediccion de llenado) │
├──────────────────────────────────────────────────────────┤
│ JOBS │
│ GC: ultimo 2h ago, duro 12min, libero 5.2GB [OK]│
│ Verify: ultimo 1d ago, 45 snaps ok, 0 errores [OK]│
│ Sync: ultimo 25d ago, desde pbs3343, 10.7GB [OK]│
│ Proximo sync: dia 15 a las 09:23 │
├──────────────────────────────────────────────────────────┤
│ [Tabla] Snapshots recientes │
│ vm/101 2026-03-12 12.3GB verified │
│ vm/101 2026-03-11 12.1GB verified │
│ vm/102 2026-03-12 8.7GB outdated │
└──────────────────────────────────────────────────────────┘
```
### Dashboard 3: Capacidad y planificacion (para management)
```
┌─────────────────────────────────────────────────────────┐
│ CAPACITY PLANNING │
├──────────────────────────────────────────────────────────┤
│ Pool9: 85TB usados / 120TB total (71%) │
│ [Grafico] Tendencia 12 meses + prediccion │
│ "Al ritmo actual, pool9 se llena en 8 meses" │
├──────────────────────────────────────────────────────────┤
│ [Tabla] Clientes por crecimiento mensual │
│ cliente3: +15GB/mes (el que mas crece) │
│ cliente1: +12GB/mes │
│ cliente7: +8GB/mes │
├──────────────────────────────────────────────────────────┤
│ [Tabla] Clientes con quota sobredimensionada │
│ cliente15: usa 20GB de 600GB quota (3%) │
│ cliente22: usa 45GB de 600GB quota (7.5%) │
│ "Oportunidad de reclamar 1.1TB de quota" │
├──────────────────────────────────────────────────────────┤
│ Resumen comercial │
│ Clientes activos: 40 │
│ GB comerciales vendidos: 8,200 GB │
│ GB reales usados: 28,500 GB (ratio 3.5x real) │
│ GB quota asignada: 49,200 GB (ratio 6x) │
└──────────────────────────────────────────────────────────┘
```

502
04-decision-logs.md Normal file
View file

@ -0,0 +1,502 @@
# Decision: Logs centralizados (punto 1.4)
## Por que es critico
En este incidente, el backdoor capturo credenciales durante 4 dias en `/var/log/ssh_auth.log`. Ese fichero estaba **solo en el servidor comprometido**. Si el atacante lo hubiera borrado (trivial con acceso root), no habria quedado evidencia de que contraseñas fueron robadas ni desde cuando.
Los logs locales en un servidor comprometido no son fiables. Necesitamos que los logs salgan del servidor **en tiempo real** a un sitio que el atacante no pueda tocar.
---
## Que logs centralizar (minimo viable)
### Prioridad 1 - Seguridad (dia 1)
| Log | Que contiene | Por que es critico |
|-----|-------------|-------------------|
| `auth.log` | Logins SSH, sudo, fallos de autenticacion, PAM events | Detecta accesos no autorizados, brute force, uso de credenciales robadas |
| `syslog` | Eventos de sistema, servicios que arrancan/paran, errores kernel | Detecta cambios de configuracion, servicios sospechosos, fallos |
| Firewall PVE (`pvefw-logger`) | Conexiones bloqueadas y permitidas por regla | Detecta intentos de conexion al C2, escaneos, trafico anormal |
### Prioridad 2 - Operaciones (semana 1-2)
| Log | Que contiene | Por que es critico |
|-----|-------------|-------------------|
| PBS task logs | Resultado de GC, verify, sync jobs | Detecta jobs fallidos antes de que el exporter reporte |
| PBS API log | Peticiones a la API de PBS | Detecta accesos sospechosos a datastores, intentos de borrado |
| ZFS events (`zed`) | Scrub results, errores de disco, pool events | Detecta degradacion de hardware antes de que falle |
### Prioridad 3 - Infraestructura (mes 1)
| Log | Que contiene | Por que es critico |
|-----|-------------|-------------------|
| Docker logs (VMs) | Stdout/stderr de contenedores | Errores de PowerDNS, Traefik, MariaDB |
| dpkg.log | Paquetes instalados/actualizados/eliminados | Detecta instalacion de software no autorizado |
| cron logs | Ejecucion de cron jobs | Detecta cron jobs añadidos o modificados |
| Proxmox cluster logs | Eventos del cluster PVE | Problemas de quorum, migraciones, fallos |
---
## Opciones evaluadas
### Opcion A: Grafana Loki + Alloy (RECOMENDADA)
#### Que es
Loki es un sistema de logs diseñado por Grafana Labs. No indexa el contenido de los logs (como Elasticsearch), sino solo las etiquetas (labels). Esto lo hace **mucho mas ligero** en CPU, RAM y disco.
Alloy (antes Promtail + Grafana Agent) es el recolector que envia logs a Loki.
#### Por que encaja
Ya hemos elegido VictoriaMetrics + Grafana para metricas. Añadir Loki significa:
- **Mismo Grafana** para metricas Y logs (una sola UI)
- Correlacion directa: ver un pico de CPU en Grafana y saltar a los logs de ese servidor en el mismo momento
- LogQL (lenguaje de consulta) es similar a PromQL
- Misma filosofia de labels que Prometheus/VictoriaMetrics
#### Arquitectura
```
Servidores PBS/PVE VM Monitoring
┌──────────────────┐ ┌─────────────────────┐
│ Grafana Alloy │──push logs──> │ Loki │
│ (en cada server) │ │ (almacen de logs) │
│ │ │ │
│ Lee: │ │ Grafana │
│ - /var/log/auth │ │ (consulta Loki + │
│ - /var/log/syslog│ │ VictoriaMetrics) │
│ - journald │ │ │
│ - PBS logs │ │ VictoriaMetrics │
│ - PVE firewall │ │ (metricas) │
└──────────────────┘ └─────────────────────┘
```
#### Alloy vs Promtail
Promtail era el recolector original de Loki. Grafana lo ha reemplazado por **Alloy** (un agente unificado que hace log shipping, metricas, y traces):
| Aspecto | Promtail (legacy) | Alloy (actual) |
|---------|-------------------|----------------|
| Estado | En mantenimiento, no nuevas features | Desarrollo activo |
| Funcion | Solo logs | Logs + metricas + traces |
| Config | YAML propio | River (nuevo formato, mas potente) |
| Puede reemplazar a | Solo Promtail | Promtail + node_exporter + vmagent |
**Recomendacion**: Si desplegais Alloy para logs, podeis usarlo tambien como recolector de metricas (reemplaza node_exporter + vmagent en cada servidor). Un solo agente para todo. Pero esto añade complejidad inicial; se puede empezar con Alloy solo para logs y expandir despues.
#### Dimensionamiento Loki
Para 100-500 servidores:
| Parametro | 100 servers | 500 servers |
|-----------|-------------|-------------|
| Ingestion estimada | ~5GB/dia | ~25GB/dia |
| Almacenamiento (30 dias) | ~50GB comprimido | ~250GB comprimido |
| RAM Loki | 2-4 GB | 4-8 GB |
| CPU Loki | 2 vCPU | 4 vCPU |
| RAM Alloy por servidor | 30-50 MB | 30-50 MB |
Loki comprime los logs agresivamente (5-10x). 30 dias de 500 servidores caben en ~250GB.
**Despliegue**: single-node mode (monolitico). Suficiente hasta ~1000 servidores. Mas alla, se escala a microservices mode.
#### Almacenamiento backend
Loki puede guardar los logs en:
- **Filesystem local** (simple, para empezar)
- **S3/Minio** (recomendado para produccion, separacion compute/storage)
- **GCS/Azure Blob** (si usais cloud)
**Recomendacion para empezar**: filesystem local en la VM de monitoring. Migrar a Minio/S3 cuando necesiteis mas retencion o redundancia.
#### Configuracion Alloy en cada servidor
```river
// /etc/alloy/config.alloy
// Recoleccion de logs para envio a Loki
// === FUENTE: Journal (systemd) ===
loki.source.journal "system" {
forward_to = [loki.write.default.receiver]
labels = {
job = "systemd",
host = env("HOSTNAME"),
component = "journal",
}
// Solo unidades relevantes
matches = "_TRANSPORT=syslog OR _TRANSPORT=kernel OR _SYSTEMD_UNIT=sshd.service OR _SYSTEMD_UNIT=proxmox-backup-proxy.service OR _SYSTEMD_UNIT=proxmox-backup.service OR _SYSTEMD_UNIT=pvedaemon.service OR _SYSTEMD_UNIT=pveproxy.service OR _SYSTEMD_UNIT=pve-firewall.service"
}
// === FUENTE: auth.log (critico para seguridad) ===
local.file_match "auth" {
path_targets = [{"__path__" = "/var/log/auth.log"}]
}
loki.source.file "auth" {
targets = local.file_match.auth.targets
forward_to = [loki.write.default.receiver]
labels = {
job = "auth",
host = env("HOSTNAME"),
}
}
// === FUENTE: syslog ===
local.file_match "syslog" {
path_targets = [{"__path__" = "/var/log/syslog"}]
}
loki.source.file "syslog" {
targets = local.file_match.syslog.targets
forward_to = [loki.write.default.receiver]
labels = {
job = "syslog",
host = env("HOSTNAME"),
}
}
// === FUENTE: PVE firewall ===
local.file_match "pvefw" {
path_targets = [{"__path__" = "/var/log/pve-firewall.log"}]
}
loki.source.file "pvefw" {
targets = local.file_match.pvefw.targets
forward_to = [loki.write.default.receiver]
labels = {
job = "pve-firewall",
host = env("HOSTNAME"),
}
}
// === FUENTE: dpkg (instalacion de paquetes) ===
local.file_match "dpkg" {
path_targets = [{"__path__" = "/var/log/dpkg.log"}]
}
loki.source.file "dpkg" {
targets = local.file_match.dpkg.targets
forward_to = [loki.write.default.receiver]
labels = {
job = "dpkg",
host = env("HOSTNAME"),
}
}
// === DESTINO: Loki central ===
loki.write "default" {
endpoint {
url = "http://loki.monitoring.internal:3100/loki/api/v1/push"
}
}
```
#### Configuracion Loki (single-node)
```yaml
# /etc/loki/loki.yaml
auth_enabled: false
server:
http_listen_port: 3100
log_level: warn
common:
path_prefix: /data/loki
storage:
filesystem:
chunks_directory: /data/loki/chunks
rules_directory: /data/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2026-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 30d # 30 dias de retencion
max_query_series: 1000
ingestion_rate_mb: 20 # 20MB/s ingestion (sobra para 500 servers)
ingestion_burst_size_mb: 40
compactor:
working_directory: /data/loki/compactor
retention_enabled: true
delete_request_cancel_period: 24h
```
#### Consultas utiles en LogQL (desde Grafana)
```logql
# Logins SSH exitosos (quien entro y desde donde)
{job="auth", host="ns31787946"} |= "Accepted"
# Intentos de login fallidos
{job="auth"} |= "Failed password" | pattern `Failed password for <user> from <ip>`
# Alguien instalo un paquete
{job="dpkg"} |= "install" | pattern `<_> install <package> <_> <version>`
# Firewall: conexiones bloqueadas al C2
{job="pve-firewall"} |= "DROP" |= "91.208.162"
# Errores en PBS
{job="systemd", host=~"pbs.*"} |= "error" | logfmt
# Todo lo que paso en un servidor en los ultimos 30 minutos
{host="ns31787946"} | line_format "{{.job}}: {{__line__}}"
# Top 10 IPs con mas intentos fallidos de SSH
{job="auth"} |= "Failed password" | pattern `from <ip> port` | count by (ip) | topk(10, count)
```
#### Alertas en Loki (via Grafana alerting o Loki ruler)
```yaml
# Alerta: mas de 10 intentos fallidos de SSH en 5 minutos
- alert: SSHBruteForce
expr: |
count_over_time({job="auth"} |= "Failed password" [5m]) > 10
for: 1m
labels:
severity: warning
# Alerta: login SSH desde IP no conocida
- alert: SSHUnknownIP
expr: |
count_over_time({job="auth"} |= "Accepted" |~ "(?!83\\.50\\.21|213\\.32\\.37|178\\.33\\.167|37\\.133\\.200)" [5m]) > 0
for: 0m
labels:
severity: critical
# Alerta: paquete instalado fuera de ventana de mantenimiento
- alert: UnexpectedPackageInstall
expr: |
count_over_time({job="dpkg"} |= "install" [5m]) > 0
for: 0m
labels:
severity: warning
# Alerta: alguien modifico PAM (habria pillado el backdoor)
- alert: PAMModification
expr: |
count_over_time({job="syslog"} |= "pam_exec" [5m]) > 0
for: 0m
labels:
severity: critical
```
---
### Opcion B: Graylog
#### Que es
Plataforma de gestion de logs con busqueda, alertas, dashboards, y pipelines de procesamiento. Usa Elasticsearch/OpenSearch como backend.
#### Ventajas sobre Loki
- **Busqueda full-text indexada**: buscar en el contenido de los logs es instantaneo (Loki es mas lento en busquedas sin label)
- **Pipelines de procesamiento**: parsear, enriquecer, transformar logs antes de almacenar
- **UI de logs dedicada**: pensada exclusivamente para analisis de logs (Grafana es mas generica)
- **Alertas de log nativas**: sin necesitar Grafana
- **Extractor de campos**: parsea syslog, JSON, etc. automaticamente
#### Desventajas
- **Requiere Elasticsearch/OpenSearch + MongoDB**: 3 componentes pesados
- **Consumo de recursos**: minimo 4GB RAM solo para Elasticsearch, 2GB para Graylog, 1GB para MongoDB = **7GB minimo**
- **Otro UI**: metricas en Grafana, logs en Graylog. Dos sitios diferentes para investigar un problema
- **Mas complejo de operar**: Elasticsearch necesita cuidado (shards, indices, GC de Java)
- **No correlacion directa** metricas-logs en una sola vista
#### Veredicto
**Potente pero pesado.** Si el equipo ya conoce Graylog/ELK, es buena opcion. Si empezais de cero, el overhead operacional y de recursos no se justifica cuando Loki + Grafana cubre el 90% de las necesidades con un tercio de los recursos.
---
### Opcion C: ELK Stack (Elasticsearch + Logstash + Kibana)
#### Veredicto rapido
**Descartado para vuestro caso.** ELK es el estandar de la industria para logs a gran escala, pero:
- Elasticsearch consume minimo 8-16GB RAM para ser usable
- Kibana es otra UI separada de Grafana
- Logstash es Java y consume mucho
- A 100-500 servidores, es matar moscas a cañonazos
- El coste operacional de mantener un cluster Elasticsearch no compensa
Si algun dia superais los 5000 servidores o necesitais cumplir regulaciones que exigen SIEM certificado, evaluarlo. Para ahora, no.
---
## Comparativa final
| Aspecto | A: Loki + Alloy (RECOMENDADA) | B: Graylog | C: ELK |
|---------|-------------------------------|-----------|--------|
| RAM backend | 2-4 GB (100 servers) | 7+ GB | 16+ GB |
| Disco (30 dias, 100 servers) | ~50 GB | ~200 GB | ~300 GB |
| Complejidad operacional | Baja | Media-alta | Alta |
| UI | Grafana (ya la tenemos) | Propia (separada) | Kibana (separada) |
| Correlacion metricas-logs | Nativa en Grafana | No directa | No directa |
| Busqueda full-text | Lenta sin labels | Rapida (indexada) | Rapida (indexada) |
| Parseo de logs | Basico (LogQL patterns) | Potente (pipelines) | Muy potente (Logstash) |
| Alertas sobre logs | Grafana alerting / Loki ruler | Nativas | ElastAlert / Kibana |
| Agente | Alloy (30-50MB RAM) | Sidecar/Filebeat | Filebeat (similar) |
| Ecosistema Grafana | Nativo | Plugin | Plugin |
---
## Recomendacion: Opcion A (Loki + Alloy)
### Razon principal
Ya tenemos Grafana y VictoriaMetrics. Loki se integra nativamente. Un solo panel para metricas + logs + alertas. El equipo aprende una sola herramienta.
### Despliegue en fases
**Fase 1 (dia 1-2): Seguridad minima**
1. Desplegar Loki single-node en la VM de monitoring (junto a VictoriaMetrics y Grafana)
2. Desplegar Alloy en todos los PBS/PVE via Ansible
3. Recolectar solo: `auth.log` + `syslog`
4. Configurar alerta de "login desde IP no conocida"
5. Verificar que los logs llegan consultando en Grafana
**Fase 2 (semana 1): Operaciones**
1. Añadir fuentes: firewall PVE, dpkg.log, PBS logs (journald)
2. Alertas: brute force SSH, instalacion de paquetes, errores PBS
3. Dashboard de logs de seguridad en Grafana
**Fase 3 (semana 2-3): Visibilidad completa**
1. Añadir Docker logs desde VMs (PowerDNS, Traefik, etc.)
2. Labels enriquecidos: tipo de servidor (pbs/pve/dns), cliente, datacenter
3. Dashboard correlacionado: metricas + logs en la misma vista temporal
**Fase 4 (mes 2): Retencion y backup**
1. Evaluar migracion de filesystem a Minio/S3 para retencion larga
2. Backup de Loki data
3. Retencion diferenciada: auth.log 90 dias, syslog 30 dias, dpkg 180 dias
---
## Diagrama del stack completo (Capa 1: Visibilidad + Capa 2: Seguridad)
```
┌─────────────────────────────────────┐
│ AUTHENTIK │
│ SSO + MFA centralizado │
│ (todos los paneles web se │
│ autentican contra Authentik) │
└──────────────────┬──────────────────┘
│ SSO
┌────────────────────────────┼────────────────────────────┐
│ │ │
┌─────────▼─────────┐ ┌─────────────▼──────────┐ ┌────────────▼───────────┐
│ GRAFANA │ │ Wazuh Dashboard │ │ Forgejo / Semaphore │
│ (UI unificada) │ │ (seguridad) │ │ Netbox / Vaultwarden │
│ Metricas + Logs │ │ FIM, rootkits, vulns │ │ (todos con SSO) │
│ Alertas→Telegram │ │ Alertas→Telegram │ │ │
└───┬──────────┬────┘ └────────────┬───────────┘ └────────────────────────┘
│ │ │
┌───▼──────┐ ┌▼───────────┐ ┌──────▼───────────┐
│Victoria │ │ Loki │ │ Wazuh Manager │
│Metrics │ │ (logs) │ │ (analisis) │
│(metricas)│ │ ret. 30d │ │ + vuln detect │
│ ret. 1a │ │ │ │ │
└───┬──────┘ └─┬──────────┘ └──────┬───────────┘
│ │ │
┌───▼──────┐ │ │
│ vmagent │ │ │
│ (scrape) │ │ │
└───┬──────┘ │ │
│ │ │
╔═══╪══════════╪═════════════════════╪════════════════════════════════╗
║ │ │ │ ║
║ │ Cada servidor de produccion (PBS/PVE/Linux gestionado): ║
║ │ ║
║ │ ┌──────────────┐ ┌────────┐ ┌───────────┐ ┌───────────────┐ ║
║ │ │node_exporter │ │ Alloy │ │Wazuh Agent│ │CrowdSec │ ║
║ │ │(metricas) │ │(logs) │ │(FIM+HIDS) │ │+ Fail2ban │ ║
║ │ │ 5MB RAM │ │ 30-50MB│ │ 50-100MB │ │ ~80MB │ ║
║ │ │+textfile jobs│ │→ Loki │ │→ Wazuh Mgr│ │ │ ║
║ │ └──────────────┘ └────────┘ └───────────┘ └───────────────┘ ║
║ │ + auditd (ya instalado, 0 extra) ║
║ │ + SSH solo desde Bastion (iptables) ║
║ │ ║
║ │ Total overhead por servidor: ~200-250 MB RAM ║
╚═══╪═════════════════════════════════════════════════════════════════╝
│ Centralizados (VM monitoring):
│ ┌─────────────────────────────────┐
├──│ pbs-exporter (natrontech) │
│ │ - multi-target: todos los PBS │
│ │ - pve_exporter: clusters PVE │
│ └─────────────────────────────────┘
│ Complementarios:
│ ┌──────────────────┐ ┌──────────────────┐
│ │ Uptime Kuma │ │ Bastion SSH │
│ │ checks binarios │ │ grabacion sesion│
│ │ SSL, DNS, HTTP │ │ ProxyJump (-J) │
│ └──────────────────┘ └──────────────────┘
Inventario + Secretos:
┌──────────────────┐ ┌──────────────────┐
│ Netbox │ │ Vaultwarden │
│ SSOT ← ICSMgr │ │ secretos equipo │
│ → Ansible inv. │ │ (SSO Authentik) │
│ → Prometheus SD │ │ │
└──────────────────┘ └──────────────────┘
```
---
## Recursos totales del stack completo (Capa 1 + Capa 2)
### VMs centrales
| VM | Componentes | CPU | RAM | Disco |
|----|-----------|-----|-----|-------|
| **Monitoring** | VictoriaMetrics + vmagent + Loki + Grafana + Alertmanager + exporters | 4 vCPU | 8-12 GB | 200-500 GB |
| **Wazuh** | Wazuh Manager + Dashboard (OpenSearch) | 4 vCPU | 12 GB | 100 GB |
| **Zammad** | Zammad + PostgreSQL + Redis + Elasticsearch | 2-3 vCPU | 4-6 GB | 50 GB |
| **Authentik** | Authentik + PostgreSQL + Redis | 1-2 vCPU | 2-3 GB | 20 GB |
| **Netbox** | Netbox + PostgreSQL + Redis | 1-2 vCPU | 2-3 GB | 20 GB |
| **ICSManager** | ICSManager + PostgreSQL (todo Docker) | 1-2 vCPU | 2-3 GB | 20 GB |
| **WildDuck** | WildDuck + MongoDB + Redis (todo Docker) | 1-2 vCPU | 2-3 GB | 30-50 GB |
| **Outline** | Outline + PostgreSQL + Redis | 1 vCPU | 1-2 GB | 20 GB |
| **Servicios** | Semaphore + Uptime Kuma + Technitium + Traefik (stateless) | 1-2 vCPU | 2-3 GB | 20 GB |
| **Bastion** | SSH jump host + grabacion sesiones | 1 vCPU | 1 GB | 20 GB |
| **WG Hub A** | WireGuard hub master + wgdashboard + nftables + NAT CGNAT | 1 vCPU | 512 MB | 10 GB |
| **WG Hub B** | WireGuard hub backup (keepalived HA) | 1 vCPU | 512 MB | 10 GB |
| **PDM** | Proxmox Datacenter Manager (gestion multi-cluster) | 1 vCPU | 1-2 GB | 20 GB |
| **PMG** | Proxmox Mail Gateway (SpamAssassin + ClamAV + quarantine) | 1-2 vCPU | 2-3 GB | 30 GB |
| **Forgejo** | Ya desplegado (repos desarrollo + nuevos repos infra) | existente | existente | existente |
| **Total VMs centrales** | | **~24-32 vCPU** | **~44-58 GB** | **580-920 GB** |
Modelo: una VM = un servicio (caja negra). Cada servicio con BBDD tiene su propia VM dedicada. App + BBDD + Redis todo dentro. Se backupea, migra y diagnostica como unidad. PDM gestiona migracion cross-cluster. PMG filtra correo entrante/saliente delante de WildDuck.
Nota disco VM Monitoring: VictoriaMetrics (retencion 1 año, ~200GB) + Loki (retencion 30 dias, ~50-250GB segun servidores). A 500 servidores, considerar separar Loki en su propio disco/VM.
Infra de backup (Capa 6, ademas de las VMs centrales):
- PBS1 (Alemania): ya existente
- PBS2 (Polonia): servidor fisico nuevo por contratar (solo disco grande, CPU/RAM minimos)
- PBS3 (opcional por cliente premium): otro proveedor/pais, coste repercutido al cliente
- Replica oficina: servidor Xeon 96GB existente (coste 0)
Recomendacion servidor fisico: 128 GB RAM, 8-12c/16-24t, 2x2TB NVMe (ZFS mirror)
### En cada servidor de produccion (PBS/PVE/Linux)
| Componente | CPU | RAM |
|-----------|-----|-----|
| Grafana Alloy (logs) | <0.1 | 30-50 MB |
| node_exporter (metricas) | <0.1 | 5-10 MB |
| Wazuh Agent (FIM+HIDS) | <0.1 | 50-100 MB |
| CrowdSec | <0.1 | ~50 MB |
| Fail2ban | <0.1 | ~30 MB |
| auditd | ya instalado | 0 extra |
| pbs-jobs-metrics.sh (cron) | despreciable | despreciable |
| **Total por servidor** | **~0.2 vCPU** | **~200-250 MB** |
Frente a Checkmk/Zabbix agent que consume 200-500MB **solo para monitoring**, aqui tenemos monitoring + logs + HIDS + IPS por ~250MB. En servidores de 32-256GB, pasa completamente desapercibido.