Fleet: Beszel hub integration — rich per-node metrics + per-node monitor (Phase 1)
Tap each node's Beszel metrics (GPU/temps/disk-IO/network/per-container — beyond
our basic heartbeat) by reading the workspace's Beszel hub. The agents run in
WS-only mode with no locally-readable socket, so (per the de-risk) the server taps
the hub's PocketBase API instead of the daemon reading agents — no daemon changes.
- migrations: workspace_beszel (BYO hub URL + login, server-side only, mirrors the
Tailscale BYO pattern) + node_metrics (latest scalar columns + JSONB blob).
- cm-db: repo/fleet_beszel.rs, repo/node_metrics.rs; nodes SELECT joins node_metrics
(gpu_pct/temp_max surfaced on node_json for the live cards).
- cm-api: beszel.rs client (auth-with-password, poll `systems`, map to nodes by
hostname, upsert metrics) + a 15s spawn_poller; routes/beszel.rs (connect/status/
disconnect + GET /api/nodes/{id}/metrics with history proxied live from the hub).
- frontend: HostCard gains a GPU/temp readout + a Monitor button; NodeMonitor is a
full-width per-node page (current panel + CPU/mem/GPU/temp/net/disk charts from the
hub's 1m history); a "Beszel monitoring" connect form in the Local view.
Reachability confirmed: gw-04 → the hub over the tailnet (100.123.224.84:8090). Needs
the user to connect their hub login to activate the poller.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
4de2f31b50
commit
36a227566b
@@ -37,6 +37,8 @@ fn node_json(n: &nodes::NodeRow) -> Value {
|
||||
"tailscaleIp": n.tailscale_ip,
|
||||
"lastSeen": n.last_seen.map(|t| t.unix_timestamp()),
|
||||
"createdAt": n.created_at.unix_timestamp(),
|
||||
"gpuPct": n.gpu_pct,
|
||||
"tempMax": n.temp_max,
|
||||
"health": n.health.as_ref().map(|h| json!({
|
||||
"cpuPct": h.cpu_pct,
|
||||
"memTotal": h.mem_total,
|
||||
|
||||
Reference in New Issue
Block a user