ProxUI
Multi-Tenant-Konsole fuer Proxmox auf Basis von Go, Supabase Postgres/Auth, Redis/asynq und React.
Architektur
backend/: HTTP-API, Auth/JWT-Validierung, RBAC, DB-Zugriff und Proxmox-Orchestrierungworker/: asynchrone Jobs fuer Proxmox-Tasks, Reconciliation und Cleanupconsole-proxy/: Websocket-Proxy fuer noVNC/xterm.js ohne direkte Proxmox-Verbindung im Browserplatform/: gemeinsame Go-Bausteine fuer Konfiguration, Logging und spaetere Querschnittsfunktionenfrontend/: React/TypeScript/Vite-App fuer Kunden- und Admin-Workflowsmigrations/: versionierte SQL-Migrationendeploy/: lokale und spaetere Deployment-Artefakte
Lokales Setup
- Go >= 1.22 installieren.
- Node.js >= 20 und npm installieren.
- Docker Desktop oder kompatible Docker Engine installieren.
.env.examplenach.envkopieren und lokale Werte setzen.- Abhaengigkeiten installieren:
npm install --prefix frontend. - Go-Abhaengigkeiten installieren:
go work sync. - Lokale Infrastruktur starten:
make dev. - Migrationen ausfuehren:
make migrate. - Backend starten:
go run ./backend/cmd/api. - Console-Proxy starten:
go run ./console-proxy/cmd/console-proxy. - Frontend starten:
npm run dev --prefix frontend.
Supabase self-hosted liegt unter deploy/supabase/. Die lokale deploy/supabase/.env wird aus der offiziellen Vorlage erzeugt und nicht committed. Fuer App-.env die Werte POSTGRES_PASSWORD, ANON_KEY und SERVICE_ROLE_KEY aus deploy/supabase/.env uebernehmen.
Migrationen nutzen MIGRATE_DATABASE_URL, falls gesetzt. Andernfalls wird DATABASE_DIRECT_URL aus .env oder eine lokale Supavisor-URL aus deploy/supabase/.env verwendet.
Das Backend validiert Supabase-JWTs ueber SUPABASE_JWKS_URL und SUPABASE_ISSUER. Fuer das lokale Self-Hosted-Setup mit leerem JWKS wird zusaetzlich SUPABASE_JWT_SECRET als HS256-Fallback genutzt. Beim ersten authentifizierten Request synchronisiert das Backend den Supabase-User lazy nach public.profiles.
Cluster-Tokens werden mit AES-256-GCM verschluesselt. MASTER_KEY_BASE64 muss ein base64-kodierter 32-Byte-Key sein, zum Beispiel erzeugt mit openssl rand -base64 32. Ohne gueltigen Master-Key bricht der Backend-Start ab.
Das Cluster-Repository speichert Proxmox-Token-Secrets nur als Ciphertext in public.clusters.encrypted_token. Entschluesselte Tokens bleiben interne Runtime-Daten und werden nicht in API-DTOs dokumentiert.
Der Proxmox-Client nutzt HTTPS mit normaler Zertifikatsvalidierung plus SHA-256-Fingerprint-Pinning gegen clusters.tls_fingerprint. Proxmox-Token werden nur als PVEAPIToken=<token_id>=<secret> Header an Proxmox gesendet.
Interne Cluster-Admin-Routen unter /internal/clusters sind nicht tenant-gebunden. Sie erfordern den Header X-ProxUI-Operator-Token mit OPERATOR_TOKEN und die isolierte Rolle operator; Responses enthalten nie token_secret.
Der Worker nutzt asynq gegen REDIS_ADDR, pingt beim Start dieselbe Supabase-DB ueber DATABASE_URL, entschluesselt Cluster-Credentials mit MASTER_KEY_BASE64 und nutzt den gemeinsamen Proxmox-Client aus platform/proxmox fuer UPID-Polls.
Lokale Dienste:
- Supabase API Gateway:
http://localhost:8000 - Supabase Studio:
http://localhost:8000/project/default - Supavisor Session Pooler:
localhost:5432 - Supavisor Transaction Pooler:
localhost:6543
Aktuelle Targets:
make test: Go-Testsmake build: Go-Buildsmake frontend-build: Frontend-Production-Buildmake lint: Go Vet und Frontend-ESLintmake verify: Lint, Tests und Buildsmake dev-down: Supabase-Stack stoppenmake dev-logs: Supabase-Logs verfolgenmake migrate: Migrationen auf den aktuellen Stand bringenmake migrate-down: letzte Migration zurueckrollenmake migrate-version: aktuelle Migrationsversion anzeigen
Worker-Jobs:
proxui.dummy: Dummy-Job mit Payload{"message":"..."}fuer Smoke-Tests der asynq-Verarbeitungproxmox.task.poll: Pollt einen Proxmox-UPID ueber den gespeicherten Cluster, setzt VM-Status auf Erfolgs- oder Fehlerstatus und schreibt Audit-Metadaten.
Backend-Endpunkte:
GET /healthz: oeffentlicher HealthcheckGET /me: geschuetzt, synchronisiertprofilesund gibt den authentifizierten Principal aus dem JWT zurueckGET /tenants/{tenantID}/membership: geschuetzt, synchronisiertprofiles, prueft Tenant-Mitgliedschaft und gibt Rolle/Tenant zurueckGET /projects/{projectID}/vms: geschuetzt, listet nur VMs aus Projekten, deren Tenant der Nutzer angehoertGET /vms/{vmID}: geschuetzt, gibt VM-Details nur bei Tenant-Mitgliedschaft zurueckPOST /vms/{vmID}/start: geschuetzt, prueftvm.power, ruft Proxmox auf und queued UPID-PollingPOST /vms/{vmID}/stop: geschuetzt, prueftvm.power, ruft Proxmox auf und queued UPID-PollingPOST /vms/{vmID}/reboot: geschuetzt, prueftvm.power, ruft Proxmox auf und queued UPID-PollingPOST /internal/clusters: intern, legt Cluster an und speichert Token verschluesseltPUT /internal/clusters/{clusterID}: intern, aktualisiert Cluster und rotiert TokenPATCH /internal/clusters/{clusterID}/status: intern, setzt Cluster-Status
Tenant-gescoped Backend-Routen laufen ueber JWT-Auth, Profil-Sync, Membership-Resolver und deklarative RBAC-Pruefung.
Frontend-Prototyp:
- Supabase Login/Registrierung ueber
VITE_SUPABASE_URLundVITE_SUPABASE_ANON_KEY - Backend-Profilcheck ueber
GET /me - Platzhalter-Ansichten fuer Projekte, VMs, SSH-Keys, Audit und Konsole
CI
Forgejo Actions laufen unter .forgejo/workflows/ci.yml.
verify: installiert Go/Node-Abhaengigkeiten und fuehrtmake verifyaus.secret-scan: fuehrtzricethezav/gitleaks:v8.28.0mit.gitleaks.tomlaus. Die Konfiguration erlaubt nur dokumentierte Beispielwerte aus den offiziellen Supabase-Upstream-Dateien.
Sicherheitsregeln
- Nur Backend, Worker und Console-Proxy sprechen mit Proxmox.
- Proxmox-Tokens werden nie im Frontend sichtbar und nie unverschluesselt gespeichert.
- Tenant-bezogene Queries muessen immer tenant-gefiltert sein.
- Secrets gehoeren in
.envoder einen Secret-Manager, nie ins Repo.