Add Proxmox integration

Fifth live integration: VM/LXC status across every online node in the
cluster, with start/stop/restart actions — matching the "dashboard + basic
actions" depth from the plan. Adapter built against Proxmox VE's own
published API tree (pve.proxmox.com/pve-docs/api-viewer/apidoc.js — parsed
its ~4MB ExtJS tree structure directly since it's not plain JSON) plus
community-verified docs for the token auth header format, since the user's
instance isn't reachable from here.

server/src/integrations/proxmox/adapter.ts: GET /nodes for online nodes,
then GET /nodes/{node}/{qemu,lxc} per node in parallel (Promise.all) and
flattened, tagging each guest with its node and type; POST
/nodes/{node}/{qemu,lxc}/{vmid}/status/{start,stop,reboot} for actions (all
confirmed token-auth-eligible via the spec's "allowtoken" flag). Uses
node:https directly (like the cPanel DNS adapter) rather than fetch, since
Proxmox commonly runs a self-signed certificate in homelab setups — added
an "Allow self-signed certificate" checkbox field for that. Auth is
`Authorization: PVEAPIToken=<tokenId>=<tokenSecret>`, a different shape
from the other three integrations' single bearer token, so the field
schema splits it into two fields (a non-secret token ID like
"root@pam!homelab-manager" and a secret token value).

Verified: full build passes. Unreachable from here, so ran a 16-check HTTP
test against the live server: role gating, credential non-leakage,
disabled-integration blocking, invalid-guest-type and non-numeric-vmid
rejection, checkbox-only config correctly still failing required-field
validation, and the wrong_type crash-safety check for this fifth adapter
type — server stays up throughout. Real node/VM data and the actual
start/stop/restart actions still need verification once this app can reach
the user's Proxmox cluster.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
bobbanandClaude Sonnet 5 committed 2026-09-15 00:24:37 +02:00
1 parent 257ec3ec0a
commit bc72b9e152
7 files changed
+454 -1

No files matched your search

+3
View File
@@ -4,6 +4,7 @@ import { createTailscaleAdapter } from "./tailscale/adapter.js";
import { createGiteaAdapter } from "./gitea/adapter.js";
import { createDockhandAdapter } from "./dockhand/adapter.js";
import { createSemaphoreAdapter } from "./semaphore/adapter.js";
import { createProxmoxAdapter } from "./proxmox/adapter.js";
export interface PingableAdapter {
ping(): Promise<{ ok: boolean; latencyMs?: number; error?: string }>;
@@ -26,6 +27,8 @@ export function createIntegrationAdapter(type: IntegrationType, config: Integrat
return createDockhandAdapter(config as any);
case "semaphore":
return createSemaphoreAdapter(config as any);
case "proxmox":
return createProxmoxAdapter(config as any);
default:
throw new Error(`Integration type "${type}" is not implemented yet`);
}