A simpler, faster web interface for managing Proxmox VE.
See all your VMs, LXC containers, backups, and monitoring - no more clicking through 10 submenus.
Live Demo
Proxmox's native UI is great for advanced configuration… but for daily tasks (restarting a VM, checking a backup, accessing a console), it's often too low-level and too spread out.
I got tired of clicking through 3 submenus just to check a VM's status, or not having a quick overview of my entire cluster.
What this interface offers :
- One single page to see ALL your VMs and LXC containers, with quick actions
- Real-time monitoring with clean charts
- 1-click web console access
- Centralized view of backups and jobs
- Dashboard : Quick health overview of your cluster (online nodes, total CPU/RAM, machine count)
- Guests inventory : All your QEMU VMs and LXC containers on one single page, with filters and quick actions (start/stop/reboot/console)
- Node pages : Detailed status, monitoring with CPU/RAM/network charts, node shell console
- Create workflow : Wizard to create QEMU VMs or LXC containers, with simple and expert modes
- Backup management : Browse and manage your vzdump backup jobs, launch on-demand backups
- Web console : 1-click terminal access for nodes and guests (via xterm.js + WebSocket)
flowchart LR
%% Layers
subgraph UI["UI / Navigation"]
LOGIN["Login page<br/>credentials + 2FA"]
DASH["Dashboard<br/>cluster overview"]
GUESTS["Guests pages<br/>inventory + actions"]
NODES["Nodes pages<br/>status + shell"]
CREATE["Create workflow<br/>QEMU / LXC forms"]
BACKUPS["Backups pages<br/>jobs + restore context"]
CONSOLEUI["ConsoleTerminal<br/>xterm.js frontend"]
end
subgraph APP["App State / Client Runtime"]
AUTH["AuthProvider<br/>ticket restore + refresh"]
QUERY["React Query<br/>polling + caching"]
ROUTER["TanStack Router<br/>authenticated layout"]
end
subgraph API["Proxmox Integration Layer"]
CLIENT["client.ts<br/>typed Proxmox API helpers"]
PROXYFN["proxy.functions.ts<br/>termproxy POST relay"]
SSR["server.ts<br/>SSR wrapper + error handling"]
WSPROXY["console-proxy.server.ts<br/>websocket upgrade path"]
end
subgraph EXT["External Services"]
PVE["Proxmox VE API<br/>nodes / qemu / lxc / backup"]
WS["vncwebsocket<br/>live console stream"]
EDGE["HTTPS / Cloudflare / CORS<br/>allowedHosts + websocket passthrough"]
DOCKER["Docker / GHCR / deploy workflow"]
end
LOGIN --> AUTH
DASH --> QUERY
GUESTS --> QUERY
NODES --> QUERY
CREATE --> QUERY
BACKUPS --> QUERY
CONSOLEUI --> AUTH
ROUTER --> LOGIN
ROUTER --> DASH
ROUTER --> GUESTS
ROUTER --> NODES
ROUTER --> CREATE
ROUTER --> BACKUPS
AUTH --> CLIENT
QUERY --> CLIENT
CONSOLEUI --> PROXYFN
CONSOLEUI --> WSPROXY
CLIENT --> PVE
PROXYFN --> PVE
SSR --> WSPROXY
WSPROXY --> WS
PVE --> WS
CLIENT -. browser constraints .-> EDGE
WSPROXY -. websocket compatibility .-> EDGE
DOCKER --> SSR
classDef ui fill:#dbeafe,stroke:#2563eb,color:#0f172a,stroke-width:1.5px;
classDef app fill:#e9d5ff,stroke:#7c3aed,color:#111827,stroke-width:1.5px;
classDef api fill:#ccfbf1,stroke:#0f766e,color:#0f172a,stroke-width:1.5px;
classDef ext fill:#fef3c7,stroke:#d97706,color:#111827,stroke-width:1.5px;
class LOGIN,DASH,GUESTS,NODES,CREATE,BACKUPS,CONSOLEUI ui;
class AUTH,QUERY,ROUTER app;
class CLIENT,PROXYFN,SSR,WSPROXY api;
class PVE,WS,EDGE,DOCKER ext;
What this diagram highlights:
- Browser-first architecture: most product logic lives in the frontend routes and widgets.
- Ticket-based auth: session state is restored client-side and refreshed periodically.
- Thin integration layer:
client.tsis the real backbone of the app. - Console is the special case:
termproxy+ websocket flow needs extra server-side handling. - Infra matters a lot: Cloudflare, CORS, TLS and websocket passthrough are part of the architecture, not just deployment details.
git clone https://github.com/DavyLss/proxmox-control-panel.git
cd proxmox-control-panel
git checkout developdocker compose up -d --buildApp URL (default): http://localhost:8080
npm install
npm run build
npm run startImage is published to:
ghcr.io/davylss/proxmox-control-panel
Example compose reference:
services:
proxmox-control-panel:
image: ghcr.io/davylss/proxmox-control-panel:${IMAGE_TAG:-develop}
ports:
- "8080:8080"Recommended target-host pattern:
- clone repo in
/opt/proxmox-control-panel - track only
develop - update with hard reset
- redeploy with Docker Compose
Example:
git fetch origin develop
git checkout develop
git reset --hard origin/develop
docker compose pull --ignore-buildable || true
docker compose up -d --build --remove-orphansFor stable API + console behavior behind Cloudflare:
- Proxmox endpoint reachable in HTTPS
- frontend hostname allowed in
vite.config.ts(server.allowedHosts) - CORS headers correctly returned on
/api2/* - WebSocket upgrades preserved for console routes
- auth ticket/cookie compatibility handled end-to-end
If you route Proxmox through a Cloudflare Worker, ensure it handles:
- preflight (
OPTIONS) - origin-aware CORS
- websocket upgrade passthrough
- cookie forwarding/rewriting compatibility for console paths
- Login uses Proxmox authentication endpoints
- Ticket/session is restored client-side on reload
- Auto-refresh is used to keep sessions valid
- TOTP/recovery support works when Proxmox 2FA is enabled
- Frontend: React 19 + TypeScript
- App framework: TanStack Start + TanStack Router
- Build: Vite
- UI: shadcn/ui + Tailwind CSS + Radix UI
- Charts: Recharts
- Container: Docker
- Registry: GHCR
src/
components/ # UI + Proxmox widgets
lib/proxmox/ # API client, auth, console helpers
routes/ # TanStack file-based routes
.github/workflows/ # CI workflows
Dockerfile # Container image build
/docker-compose.yml # Local/target deployment
vite.config.ts # Vite + host allowlist
npm install
npm run build
npm run start
npm run lint
npm run formatUsually CORS/origin mismatch on Proxmox API routes.
Check websocket upgrade path, cookie forwarding, Proxmox permissions, and guest/node running state.
Add the hostname to vite.server.allowedHosts in vite.config.ts.
- Do not commit long-lived credentials/secrets
- Use least-privilege Proxmox accounts/tokens
- Review Cloudflare Worker behavior carefully when handling auth/cookies
- Default branch:
develop - Production updates: from validated commits on
develop - Deleted branch:
main
- Repository : https://github.com/DavyLss/proxmox-control-panel
- Live demo : https://proxmox-control-panel.lassechere.fr/





