Add SshHostCollector for .180 (omv) and .171 (ripper)
CI / web (push) Successful in 20s
CI / api (push) Successful in 27s

Extends monitoring to the two bare-metal boxes Proxmox can't see.
Uses a dedicated ed25519 key with a forced authorized_keys command
(see docs/ssh-collector-key-setup.md) so a leaked key can only ever
run the fixed read-only stats script, never arbitrary commands.

CPU is approximated from 1-min load average / core count (a true
utilization % would need two /proc/stat samples).

Closes #8.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 20:40:10 -06:00
parent ac768ed0db
commit 7df08cd16d
10 changed files with 349 additions and 0 deletions
+26
View File
@@ -1,11 +1,23 @@
import { readFileSync } from "node:fs";
import { parse } from "yaml";
import type { SshHostConfig } from "../collectors/sshHost.js";
interface RawSshHost {
id: string;
displayName: string;
group: string;
host: string;
port?: number;
username: string;
diskPaths?: { path: string; label: string }[];
}
export interface HostsConfig {
proxmox: {
host: string;
node: string;
};
sshHosts?: RawSshHost[];
}
export interface AppConfig {
@@ -26,6 +38,7 @@ export interface AppConfig {
tokenId: string;
tokenSecret: string;
};
sshHosts: SshHostConfig[];
hosts: HostsConfig;
}
@@ -37,6 +50,18 @@ function required(name: string): string {
export function loadConfig(hostsConfigPath: string): AppConfig {
const hosts = parse(readFileSync(hostsConfigPath, "utf8")) as HostsConfig;
const sshPrivateKeyPath = process.env.SSH_PRIVATE_KEY_PATH ?? "./ssh/monitor_ed25519";
const sshHosts: SshHostConfig[] = (hosts.sshHosts ?? []).map((h) => ({
id: h.id,
displayName: h.displayName,
group: h.group,
host: h.host,
port: h.port ?? 22,
username: h.username,
privateKeyPath: sshPrivateKeyPath,
diskPaths: h.diskPaths ?? [{ path: "/", label: "root" }],
}));
return {
port: Number(process.env.PORT ?? 3000),
@@ -54,6 +79,7 @@ export function loadConfig(hostsConfigPath: string): AppConfig {
tokenId: required("PROXMOX_TOKEN_ID"),
tokenSecret: required("PROXMOX_TOKEN_SECRET"),
},
sshHosts,
hosts,
};
}