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>
Homelab Manager
A single dashboard for a homelab: Proxmox, Synology DSM, Semaphore, Tailscale, Gitea, and Dockhand/Docker status and basic actions, plus DNS record management, an IP address inventory (IPAM), and a secret-expiry tracker (ported from Sloth Manager) and scheduled-task tracking across Debian/Raspbian hosts (ported from Schedule Task Manager). Looks and feels like a Tabler admin dashboard. Sign-in is delegated to Authentik (OIDC), with local admin/operator/viewer roles.
Status
Built so far:
- Monorepo scaffold, Tabler-themed app shell/navigation
- Authentik OIDC login, roles (first user to sign in becomes admin), audit log
- Secrets — expiry tracking for API tokens/certs/passwords
- IP Addresses (IPAM) — inventory of IPs across vendors/locations
- DNS — zone/record management across Cloudflare, Loopia, Pi-hole, Azure DNS, cPanel, and Technitium; providers are configured in-app (not via env vars) and their credentials are encrypted at rest
- Servers & Tasks — cron/systemd tracking across Debian/Raspbian servers
via a lightweight push agent (
agent/linux/), plus manual entries for things an agent can't see (Docker jobs, backups) - Integrations → Tailscale — device list with online/authorized status, and authorize/deauthorize/remove actions; a live device-count widget on the Dashboard.
- Integrations → Gitea — repo list with each repo's last CI run status, and re-running just the failed jobs in a run; a live repo-count widget (with a failing-build warning) on the Dashboard.
- Integrations → Dockhand — container status across every Docker host Dockhand manages (one credential covers all of them), with start/stop/restart actions; a live running/total widget on the Dashboard.
- Integrations → Semaphore — Ansible run status per template across every project, with a "Run" action to trigger a template; a live template-count widget (with a last-failed warning) on the Dashboard.
All four integrations follow the same config-in-UI + encrypted-credentials pattern as DNS providers, so the remaining ones slot into the same "Add integration" form as they're built.
Not yet built (see .claude/plans for the full delivery plan):
- Remaining live integrations: Proxmox, Synology
Requirements
- Node.js 20+
- An Authentik instance reachable from wherever this app runs
1. Set up an Authentik application
- Create an OAuth2/OpenID Provider:
- Redirect URI:
<APP_BASE_URL>/auth/callback - Scopes:
openid,email,profile
- Redirect URI:
- Create an Application using that provider, and assign the users/groups who should be able to sign in — Authentik controls who can authenticate; the app's own admin/operator/viewer roles control what they can do once in.
- Copy the provider's issuer URL, client ID, and client secret into
.env.
2. Local development
cp .env.example .env # fill in AUTHENTIK_*, SESSION_SECRET, CREDENTIALS_ENCRYPTION_KEY
npm install
npm run dev:server # http://localhost:3000 (API)
npm run dev:web # http://localhost:5173 (Vite dev server, proxies /api and /auth to :3000)
Visit http://localhost:5173 during development. Database migrations run
automatically on server start. SQLite data lands in ./data (gitignored).
Generate SESSION_SECRET and CREDENTIALS_ENCRYPTION_KEY with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
3. Run with Docker
cp .env.example .env
# edit .env
docker compose -f docker-compose.dev.yml up -d --build # build locally
# or, once an image is published to your registry:
docker compose up -d
The app listens on HOST_PORT (default 3000); SQLite data persists in
./data on the host.