Files
homelab-monitor/CLAUDE.md
T
jhodgkin 04131006ed
CI / web (push) Successful in 18s
CI / api (push) Successful in 24s
docs: record Zabbix decision, CT122 conflict, OIDC/exposure status
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 21:17:06 -06:00

5.5 KiB

Homelab Monitor — Project Memory

Unified health dashboard for the homelab (infra docs: jhodgkin/homelab repo, docs/infrastructure.md). One login instead of logging into Proxmox, Zabbix, OMV, and every service separately.

How to resume work in a new session

  1. List open issues: GET /api/v1/repos/jhodgkin/homelab-monitor/issues?state=open&limit=30 on git.jerodrigged.com (same pattern as the main homelab backlog, see global ~/.claude/CLAUDE.md). Milestone v1-dashboard is the current focus; everything else is backlog.
  2. Pick an issue, comment that you're starting it, do the work, comment what you did, close it.
  3. Commit and push after every meaningful step — don't let work sit uncommitted.

Architecture

  • apps/api — Fastify + TypeScript. Polls collectors on an interval (POLL_INTERVAL_SECONDS, default 30s), writes snapshots to SQLite (apps/api/src/db), serves /api/*.
  • apps/web — React + Vite + TypeScript. Polls /api/hosts every 15s, renders host/container cards.
  • config/hosts.yaml — declares what to monitor (no secrets, committed). Credentials live in .env (gitignored) — see .env.example for the full list.
  • Collectors implement the Collector interface (apps/api/src/collectors/types.ts) and are registered in apps/api/src/index.ts. Adding a new data source = new collector + config entry, no other wiring.
    • ProxmoxCollector (done): one API call to pve returns CPU/mem/disk and PSI pressure (pressurecpusome, pressurememoryfull) for the host + every LXC. Covers ~22 of ~24 machines.
    • SshHostCollector (done): covers .180 (omv) and .171 (ripper), the bare-metal boxes Proxmox can't see. Dedicated SSH key with a forced command= in the remote authorized_keys — the server always runs a fixed read-only script regardless of what's exec'd, so a leaked key is still contained. See docs/ssh-collector-key-setup.md, including the gotcha that diskPaths in hosts.yaml must be kept in sync by hand with the remote script's DISK_<label>= lines.
    • No Zabbix collector — see "Zabbix: intentionally skipped" below.
  • Auth: local (bcrypt + signed session cookie) is always available — it's not an exclusive mode switch. OIDC via Authentik is an additional sign-in button, live when OIDC_ENABLED=true. See docs/oidc-setup.md. Deliberately additive so OIDC config problems can never lock out the admin login.
  • Device discovery (done, separate from the collector system above — it's inventory, not per-host metrics): scripts/discover-devices.sh runs via systemd timer on the CT122 host, not in Docker (real ARP entries live in the host's network namespace, not Docker's bridge network). API reads the resulting JSON each poll cycle. Full reasoning in docs/device-discovery.md.

Infrastructure this project owns

  • Gitea repo: jhodgkin/homelab-monitor
  • Proxmox API token: monitor@pve!dashboard, role PVEAuditor (read-only), created via pveum on pve. Secret lives only in CT122's .env.
  • Deployment: CT122 (homelab-monitor, 192.168.1.103), unprivileged LXC on pve, Docker + Compose. SSH alias homelab-monitor in ~/.ssh/config (root, key-based). ⚠️ CT122 ID conflict: the main homelab repo's jhodgkin/homelab#15 (Grafana/Loki/Prometheus migration) also planned to use CT122. That issue predates this dashboard's CT122 but wasn't checked before provisioning. Flagged in a comment on that issue — when #15 is picked up, it needs a different CT ID (123 or next free).
  • SSH collector key: monitor_ed25519 keypair lives only at /opt/homelab-monitor/ssh/ on CT122 (gitignored, not in the repo). Public key installed on omv and ripper with a forced command — see docs/ssh-collector-key-setup.md.
  • Authentik OIDC provider: set up via an Authentik blueprint on CT121 (not a manual UI step) — see docs/oidc-setup.md. Purely additive, didn't touch any existing Authentik user/credential.
  • NPM proxy host: monitor.jerodrigged.com → 192.168.1.103:8090 created (id 14 in NPM), but no DNS/Cloudflare tunnel route yet — the hostname won't resolve until issue #13 finishes (needs a Cloudflare API token from the user). No SSL cert requested yet either (Let's Encrypt HTTP-01 needs the domain to actually resolve first).
  • Vaultwarden: dashboard admin credentials saved as "Homelab Monitor (dashboard admin)". OIDC client credentials not yet saved there (pending a BW_SESSION from the user).

Zabbix: intentionally skipped, not blocked

Investigated CT109 while working issue #11 and found Zabbix was never actually finished being set up (frontend not wired into Apache, setup wizard never run, no real hosts monitored, likely still on default Admin/zabbix credentials). Turned out this is expected: jhodgkin/homelab#15 already plans to decommission Zabbix entirely in favor of Prometheus+Loki+Grafana. User's call: skip Zabbix integration entirely rather than finish configuring a service that's being replaced. homelab-monitor issue #11 is closed as won't-do — if a metrics-alerting panel is wanted later, it should target Grafana/Prometheus once homelab#15 lands, as a new issue, not a reopening of #11.

Known gaps / explicitly deferred (see issues for detail)

  • No historical charts yet — only the latest snapshot is shown (24h retention in SQLite unused by the UI so far).
  • Public exposure (issue #13) is half-done: NPM proxy host exists, Cloudflare DNS/tunnel route does not. Needs a Cloudflare API token (Zero Trust: Edit) from the user to finish.