Skip to content

Infra Stack

Nota (2026-07-26 — estado real verificado): la nota anterior ("Uptime Kuma ya no existe") era FALSA — Uptime Kuma (:3001) existe, corre y es el meta-monitor oficial: vigila lo que Prometheus no puede auto-vigilar (Prometheus, Grafana, Loki, ntfy + HA y PBS; 6 monitores, avisa por Telegram/ntfy). El 2026-07-26 se podaron 6 monitores duplicados/zombis (Sonarr/Radarr/Jellyfin/Immich/n8n ya los cubre ContainerDown de Prometheus; Beszel apuntaba a un LXC destruido). Regla: cada alerta tiene un dueño único — servicios=Prometheus/Alertmanager, la propia pila de observabilidad=Kuma. Los que SÍ están retirados son Watchtower y Speedtest Tracker (0 menciones en el compose; el job speedtest de Prometheus se eliminó 2026-07-26 tras semanas marcando down).

Actualización 2026-08-01: las menciones de Watchtower/Speedtest más abajo (diagrama, tablas, comandos) se han limpiado ahora para dejar de contradecir esta nota — antes decía "ignóralas" y las dejaba igualmente escritas como si estuvieran activas, lo cual confundía más de lo que aclaraba. También se confirmó en vivo (docker ps -a + compose real en media-208) que Krawl tampoco está en el compose actual — confirmado decomisionado (fecha exacta desconocida). El directorio appdata/krawl huérfano estaba vacío (0 bytes de datos reales) → borrado 2026-08-01. Esto conectó un cabo suelto de reference/cf-access.md: las 8 apps CF Access admin/panel/login/phpmyadmin/wp-admin/cpanel/webmail/dashboard que ese doc marcaba como "no aparecen en las rutas de homelab-ctl.py, sin confirmar por qué" eran exactamente los 8 subdominios señuelo que servía Krawl — con el honeypot muerto, no protegían nada real. Borradas las 8 apps de CF Access y sus 8 registros DNS el 2026-08-01, confirmado por el propietario. Y el compose real de infra trae 4 servicios que este doc nunca mencionó: blackbox-exporter, healthchecks, pushgateway, pihole-exporter — añadidos abajo con lo mínimo verificable.

Observability, monitoring, and management services. Always running.

Compose file infra/compose.yaml
Status Always on (start first)
Dependencies None

Architecture

┌─────────────────────────────────────────────────────────────┐
│                     VISUALIZATION                            │
│  ┌──────────────┐                      ┌──────────────────┐ │
│  │   Grafana    │◄─────────────────────│    Homepage      │ │
│  │    :3030     │                      │      :80         │ │
│  └──────┬───────┘                      └──────────────────┘ │
│         │                                                    │
│    ┌────┴────┐                                              │
│    ▼         ▼                                              │
│ ┌──────┐ ┌──────┐                                           │
│ │Prom. │ │ Loki │                                           │
│ │:9090 │ │:3101 │                                           │
│ └──┬───┘ └──┬───┘                                           │
│    │        │                                               │
└────┼────────┼───────────────────────────────────────────────┘
     │        │
┌────┼────────┼───────────────────────────────────────────────┐
│    │  DATA COLLECTION                                       │
│    │        │                                               │
│    │   ┌────┴────┐                                          │
│    │   │Promtail │ ── Logs from containers & /var/log       │
│    │   └─────────┘                                          │
│    │                                                         │
│    ├──────┬──────────┐                                      │
│    ▼      ▼          ▼                                      │
│ ┌──────┐ ┌────────┐ ┌──────────────┐ ┌────────────────┐    │
│ │Node  │ │cAdvisor│ │Blackbox-exp. │ │Pihole-exporter │    │
│ │Exp.  │ │ :8084  │ │   :9115      │ │    :9617       │    │
│ │:9100 │ └────────┘ └──────────────┘ └────────────────┘    │
│ └──────┘  (+ Pushgateway :9092 — push desde jobs one-shot)  │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│                     MANAGEMENT                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │   Dockge     │  │ Healthchecks │  │ Uptime Kuma  │       │
│  │    :5001     │  │    :8073     │  │    :3001     │       │
│  └──────────────┘  └──────────────┘  └──────────────┘       │
└──────────────────────────────────────────────────────────────┘

Diagrama corregido 2026-08-01: Watchtower y Speedtest Tracker quitados (retirados, ver nota de arriba); añadidos Blackbox-exporter/Pihole-exporter/Pushgateway/Healthchecks, que sí existen en infra/compose.yaml en vivo pero nunca se habían dibujado aquí. Dockge está definido en el compose pero verificado Exited en esta pasada — no es "always on" en la práctica ahora mismo.

Services

Metrics Collection

Service Port Purpose
Prometheus 9090 Time-series metrics database
Node Exporter 9100 Host metrics (CPU, memory, disk)
cAdvisor 8084 Container metrics
Blackbox-exporter 9115 HTTP/TCP probe-based checks (not documented before 2026-08-01)
Pihole-exporter 9617 Pi-hole metrics (not documented before 2026-08-01)
Pushgateway 9092 Push endpoint for one-shot/batch jobs (not documented before 2026-08-01)

~~Speedtest Tracker | 8765 | Internet speed history~~ — retirado, ver nota al inicio del doc.

Prometheus config: /home/monxas/appdata/prometheus/prometheus.yml

Network mode: Host network (for direct access to node-exporter)

Current scrape targets (Speedtest tracker target removed 2026-08-01, job was already gone): - localhost:9090 - Self - localhost:9100 - Node exporter (host network) - 192.168.0.208:8084 - cAdvisor - 192.168.0.171:8123 - Home Assistant - 192.168.0.208:8086 - Plundrio-scanner - 192.168.0.208:8087 - Plundrio-hunter

Lista de scrape targets no reverificada exhaustivamente

Lo de arriba es la lista previa del doc menos Speedtest. No se hizo una auditoría completa de prometheus.yml real en esta pasada (por ejemplo, es probable que asus-exporter y los exporters nuevos de la tabla de arriba también estén como targets — job asus-router confirmado; el job unifi se retiró el 2026-08-09, equipo devuelto). Tratar esta lista como incompleta, no como inventario definitivo.

Turbo-boosted settings: - Retention: 30 days / 5GB max - cAdvisor housekeeping: 30s (reduced CPU) - Node-exporter: 20+ collectors disabled (arp, bcache, bonding, btrfs, infiniband, ipvs, mdadm, nfs, nfsd, rapl, schedstat, sockstat, etc.)

Alert Rules: /home/monxas/appdata/prometheus/alerts.yml

No versionado

Este fichero vive sólo en media-208 y no está gestionado por Ansible. Edítalo en caliente, valida con docker exec prometheus promtool check rules /etc/prometheus/alerts.yml y recarga con curl -X POST http://localhost:9090/-/reload.

41 reglas en 6 grupos por dominio: host_system (7), nas_health (5), nas_storage (7), nas_smart (15), backup (2), services (5). El desglose completo y el reparto con Grafana están en Alerting flow.

Grupo host_system:

  • HighDiskUsage (warning at 80%, <20% free)
  • CriticalDiskUsage (critical at 90%, <10% free)
  • HighMemoryUsage (>90%, con el ARC de ZFS sumado a MemAvailable en los nodos Proxmox)
  • LowMemoryAvailable (critical, <10% de MemTotal; umbral relativo)
  • SwapNearlyFull (>85% y con presión de memoria real, PSI > 0.05)
  • ContainerDown (todas las instancias de un job caídas >2min — no cubre proxmox-nodes; para caída de un target suelto está prom-target-down en Grafana)
  • HighLoadAverage (15min load >2 per core, excluye los jobs LXC tv-gw|n8n-node|ha-ml-node)

Por qué esas tres salvedades (2026-07-26)

Las reglas ingenuas generaban ~20 falsos positivos diarios en pmx-50 (113 HighMemoryUsage + 31 SwapNearlyFull en 7 días) con la PSI de memoria en ~0. Tres artefactos de medición:

  1. MemAvailable no contabiliza el ARC de ZFS. Es memoria reclamable al instante, pero Linux no la reporta como disponible: sobreestimaba el uso de pmx-50 en ~14 puntos (87% vs 69% real). Por eso HighMemoryUsage y LowMemoryAvailable suman node_zfs_arc_size.
  2. zram está diseñado para ir lleno. En pmx-50 el swap total es 4.3 GiB de zram + 2 GiB de disco, así que un zram lleno ya fija un suelo del 68% de swap usado. SwapNearlyFull exige además PSI real, que es el único síntoma que distingue "swap lleno" de "swap doliendo".
  3. Los LXC sin lxcfs -l leen /proc/loadavg del host. Su loadavg es un duplicado del de pmx-50/51 y no dice nada del contenedor. El resto de métricas del LXC (CPU, memoria) son container-scoped vía lxcfs, así que para vigilar contenedores usa CPU, no load.

Umbrales absolutos aplicados a contenedores pequeños son la misma clase de error: el antiguo LowMemoryAvailable < 600 MB era inalcanzable por construcción en el LXC 200 (n8n, límite 1 GiB), y disparaba en bucle.

Regla general: en pmx-50 el único síntoma que importa es /proc/pressure/memory. Los porcentajes de RAM y swap no significan nada en un host con ZFS + zram + sobreasignación intencionada (~44 GiB asignados entre VMs y LXCs sobre 28 GiB físicos).

Log Aggregation

Service Port Purpose
Loki 3101 Log storage and querying
Promtail - Log collector (ships to Loki)

Promtail config: /home/monxas/appdata/promtail/config.yml

Collects: - /var/log/* - System logs - Docker container logs via labels

Visualization

Service Port Purpose
Grafana 3030 Dashboards and alerting
Homepage 80 Static dashboard (nginx)

Grafana data: /home/monxas/appdata/grafana/

Security

Krawl decomisionado — confirmado y limpiado (2026-08-01, fecha exacta del decomiso desconocida)

No hay contenedor krawl en docker ps -a, no aparece krawl: en ~/stacks/infra/compose.yaml en vivo (solo en un backup viejo, infra/compose.yaml.bak-20260722, y en el historial git), y no se encontró ninguna ruta Caddy para admin/panel/login/etc. El directorio huérfano /home/monxas/appdata/krawl/ estaba vacío (sin datos reales que perder) → borrado. La tabla de abajo describe cómo funcionaba cuando estaba vivo — pura referencia histórica, ya no corre. No se encontró ninguna nota o memoria que explique cuándo o por qué se quitó.

Las 8 apps CF Access que le daban entrada (admin/panel/login/phpmyadmin/wp-admin/ cpanel/webmail/dashboard, ver reference/cf-access.md) ya no protegían nada real — borradas junto con sus 8 registros DNS el 2026-08-01.

Service Port Purpose
Krawl (decomisionado, sección histórica) 5050 Honeypot & IP analysis

Krawl serves fake admin/login pages to attract and log attackers. Exposed via 8 Cloudflare Tunnel subdomains: admin, panel, login, phpmyadmin, wp-admin, cpanel, webmail, dashboard (all *.monxas.casa).

Dashboard: https://admin.monxas.casa/krawl-dashboard

Data: /home/monxas/appdata/krawl/

Management & Monitoring

Service Port Purpose
Dockge 5001 Docker Compose UI (verified Exited 2026-08-01, not currently running)
Uptime Kuma 3001 Uptime monitoring with alerts
Healthchecks 8073 Dead-man's-switch style cron/job monitoring (not documented before 2026-08-01)

~~Watchtower — auto-updates at 4 AM~~ — retirado (0 menciones en el compose real, confirmado 2026-08-01), ver nota al inicio del doc. Los ajustes de abajo son históricos.

Data Retention

Service Retention Location
Prometheus 30 days / 5GB /home/monxas/appdata/prometheus/data
Loki Default /home/monxas/appdata/loki
Grafana Unlimited /home/monxas/appdata/grafana

Common Tasks

Check Prometheus targets:

curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {job: .labels.job, health: .health}'

Query Prometheus:

# CPU usage
curl -s 'http://localhost:9090/api/v1/query?query=100-(avg(irate(node_cpu_seconds_total{mode="idle"}[5m]))*100)'

# Memory usage
curl -s 'http://localhost:9090/api/v1/query?query=100*(1-node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)'

Add new Prometheus target: Edit /home/monxas/appdata/prometheus/prometheus.yml then:

docker restart prometheus

Troubleshooting

Prometheus not scraping?

# Check target status
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | select(.health != "up")'

# Check config
docker exec prometheus promtool check config /etc/prometheus/prometheus.yml

Grafana can't connect to data source?

# Test Prometheus from Grafana container
docker exec grafana curl -s http://prometheus:9090/api/v1/status/config

Logs not appearing in Loki?

# Check Promtail
docker logs promtail --tail 50

# Test Loki
curl -s http://localhost:3101/ready