Scaffold homelab-monitor: Fastify API + React dashboard + CI
CI / web (push) Failing after 1m11s
CI / api (push) Successful in 1m19s

Vertical slice for Phase 1 (v1-dashboard milestone): Proxmox collector,
SQLite storage, local auth, and a dashboard UI showing host/container
status cards. Config-driven collector registry so future data sources
(SSH-based hosts, Zabbix, network discovery) plug in without rewiring.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 20:18:44 -06:00
commit a075488f4b
33 changed files with 5175 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
import { readFileSync } from "node:fs";
import { parse } from "yaml";
export interface HostsConfig {
proxmox: {
host: string;
node: string;
};
}
export interface AppConfig {
port: number;
dbPath: string;
pollIntervalSeconds: number;
snapshotRetentionHours: number;
authMode: "local" | "oidc";
sessionSecret: string;
adminUsername: string;
adminPassword: string | undefined;
proxmox: {
host: string;
node: string;
tokenId: string;
tokenSecret: string;
};
hosts: HostsConfig;
}
function required(name: string): string {
const v = process.env[name];
if (!v) throw new Error(`Missing required env var: ${name}`);
return v;
}
export function loadConfig(hostsConfigPath: string): AppConfig {
const hosts = parse(readFileSync(hostsConfigPath, "utf8")) as HostsConfig;
return {
port: Number(process.env.PORT ?? 3000),
dbPath: process.env.DB_PATH ?? "./data/monitor.db",
pollIntervalSeconds: Number(process.env.POLL_INTERVAL_SECONDS ?? 30),
snapshotRetentionHours: Number(process.env.SNAPSHOT_RETENTION_HOURS ?? 24),
authMode: (process.env.AUTH_MODE as "local" | "oidc") ?? "local",
sessionSecret: required("SESSION_SECRET"),
adminUsername: process.env.ADMIN_USERNAME ?? "admin",
adminPassword: process.env.ADMIN_PASSWORD,
proxmox: {
host: hosts.proxmox.host,
node: hosts.proxmox.node,
tokenId: required("PROXMOX_TOKEN_ID"),
tokenSecret: required("PROXMOX_TOKEN_SECRET"),
},
hosts,
};
}