A lightweight, self-service portal for Proxmox VE that lets users create, operate, and troubleshoot virtual machines without exposing the Proxmox UI.
French version: README.fr.md
- Overview
- Feature highlights
- Architecture at a glance
- Configuration
- Deployment options
- Quick start with Docker run
- Start with Docker compose
- Start with Kubernetes
- Operations
- Limitations & roadmap
- License
PVMSS runs as a stateless web application (Go backend + HTML/CSS frontend) and relies on Proxmox APIs for every action. It is designed to be:
- Secure by default: per-user sessions.
- Operations-friendly: ready-to-use container image, configurable resource limits, cluster-aware storage selection.
- User-centric: clear and guided VM forms, built-in documentation.
⚠️ The project is still under active development. Review the Limitations & roadmap section before deploying to production.
- Create VMs with custom CPU/RAM/disk/ISO/network/tag options (EFI, TPM, multi-NIC, disk bus selection, network card model, etc.).
- Launch the Proxmox noVNC console straight from the portal (websocket proxy with session cookies).
- Start, stop, reboot, delete, and resize existing VMs.
- Search VMs by VMID or name and inspect live metrics (CPU, memory, disk, network, uptime).
- Self-service profile: list personal VMs, reset password, view quotas.
- Interface localized in English and French.
- Approve Proxmox nodes, storages, VMBRs, and ISO repositories shown to users.
- Manage tags and user pools.
- Define global VM limits plus per-node caps (CPU, RAM, disk, number of NICs/disks).
- Admin documentation and application insights page (runtime, environment, cluster status).
- Backend: Go 1.25+, RESTy client for Proxmox APIs, basic HTML templates.
- Frontend: Bulma-based, with custom CSS.
- Authentication: Proxmox API token for backend actions, user sessions for UI.
PVMSS relies on dedicated Proxmox roles and ACLs to work correctly (service account, admin accounts, per-user pools).
Before using PVMSS in production, you must:
- Create the
PVMSS_Servicerole with the expected privileges. - Create the
PVMSS_Serviceuser and its API token. - Create a
PVMSS_Adminuser (human admin to manage PVMSS app and PVMSS users). - Create the ACLs for the
PVMSS_ServiceandPVMSS_Adminusers.
In your Proxmox cluster, you can create the roles and ACLs using the pveum command-line tool. You can also create them using the Proxmox web interface. As root, create the roles and privileges:
# PVMSS_Service
pveum roleadd PVMSS_Service -privs "Sys.Audit VM.Audit VM.Allocate VM.PowerMgmt VM.Console VM.Config.CPU VM.Config.Memory VM.Config.Disk VM.Config.Network VM.Config.Options VM.Config.Cloudinit Datastore.Audit Datastore.AllocateSpace Pool.Allocate Pool.Audit User.Modify Permissions.Modify Realm.AllocateUser SDN.Allocate SDN.Audit SDN.Use"
pveum useradd pvmss-svc@pve -comment "PVMSS service account" \
-enable 1
pveum user token add pvmss-svc@pve pvmss-service-token --privsep 0
# PVMSS_Admin
pveum roleadd PVMSS_Admin -privs "Sys.Audit VM.Audit VM.PowerMgmt VM.Console VM.Config.CPU VM.Config.Memory VM.Config.Disk VM.Config.Network VM.Config.HWType VM.GuestAgent.Audit VM.Migrate VM.Config.CDROM VM.Config.Options VM.Config.Cloudinit Datastore.Audit Datastore.AllocateSpace Pool.Allocate Pool.Audit User.Modify Permissions.Modify Realm.AllocateUser SDN.Audit Group.Allocate"
pveum useradd pvmss-admin1@pve \
-comment "PVMSS administrator <name>" -password "strong_password" \
-enable 1
pveum aclmod / -user pvmss-admin1@pve -role PVMSS_Admin -propagate 1The pveum commands and information related to roles and required privileges are detailed in:
backend/docs/proxmox-permissions.en.md(in this repository)- The in-app admin page
/docs/proxmox-permissions(once PVMSS is running and you are logged in as admin)
If you want to use PVMSS in development, you must create an API token for the user root@pam. It is the simple way to get started, but keep in mind that it is the least secure way.
Go to Datacenter > Permissions > API Tokens. Click on “Add” button and select the user root@pam. Type the API token name, uncheck the case "Privilege Separations", and get the secret (will be visible only one time).
You can now use the API token in the environment variables PROXMOX_API_TOKEN_NAME and PROXMOX_API_TOKEN_VALUE.
settings.json file acts as the source of truth for every option available to users:
{
"tags": ["pvmss"],
"isos": [],
"vmbrs": [],
"enabled_storages": [],
"max_network_cards": 1,
"max_disk_per_vm": 1,
"max_vm_per_user": 3,
"limits": {
"nodes": {},
"vm": {
"sockets": {"min": 1, "max": 1},
"cores": {"min": 1, "max": 2},
"ram": {"min": 1, "max": 4},
"disk": {"min": 6, "max": 12}
}
}
}All keys are mandatory. Next versions of PVMSS can add new keys to this file, so it is recommended to keep it up to date.
The tag pvmss is used by default for VMs created via PVMSS, it cannot and should not be removed. Only PVMSS tags created by the admin from this app can be used.
You can rely on .env + env_file or inline environment: entries, but not both. The needed variables are listed below:
| Variable | Description | Required | Default |
|---|---|---|---|
ADMIN_PASSWORD_HASH |
Bcrypt hash for the admin UI login | ✅ | — |
SESSION_SECRET |
32+ byte secret to encrypt sessions/cookies | ✅ | — |
PROXMOX_API_TOKEN_NAME |
Proxmox token name (user@pve!token) used by the backend |
✅ | — |
PROXMOX_API_TOKEN_VALUE |
Token secret that matches the name above | ✅ | — |
PROXMOX_URL |
Full API URL (https://host:8006/api2/json) |
✅ | — |
PROXMOX_VERIFY_SSL |
true for trusted certs, false for self-signed labs |
❌ | false |
PVMSS_ENV |
production/prod (secure cookies + HSTS) or development/dev/developpement |
❌ | production |
PVMSS_OFFLINE |
true disables all Proxmox calls (demo mode) |
❌ | false |
PVMSS_SETTINGS_PATH |
Inside-container path to settings.json |
❌ | /app/settings.json |
LOG_LEVEL |
INFO or DEBUG |
❌ | INFO |
TZ |
Container timezone | ❌ | UTC |
Tip:
ADMIN_PASSWORD_HASHcan be generated locally withhtpasswd -bnBC 10 "admin" "StrongPassword" | cut -d: -f2.
| Platform | Notes |
|---|---|
| Docker / Podman | Recommended for quick trials or single-node installs. Mount settings.json and expose port 50000. |
| Docker Compose | Best experience: one service, reproducible environment, easy env var management. |
| Kubernetes | Use pvmss-deployment.yaml for namespace + secret + configmap + PVC + Deployment + Service. Apply with kubectl apply -f pvmss-deployment.yaml. Provide your own ingress/HTTPRoute (see pvmss-httproute.yml). |
docker run -d \
--name pvmss \
--restart unless-stopped \
-p 50000:50000 \
-v $(pwd)/settings.json:/app/settings.json \
-e ADMIN_PASSWORD_HASH='$2y$10$Ppg7Wl3sNYrmxZmWgcq4reOyznt7AeqMrQucaH4HY.dBrzavhPP1e' \
-e LOG_LEVEL=INFO \
-e PROXMOX_API_TOKEN_NAME='tokenName@changeMe!value' \
-e PROXMOX_API_TOKEN_VALUE="aaaaaaaa-0000-44aa-1111-aaaaaaaaaaa" \
-e PROXMOX_URL=https://ip-or-name:8006/api2/json \
-e PROXMOX_VERIFY_SSL=false \
-e PVMSS_ENV="prod" \
-e PVMSS_OFFLINE="false" \
-e PVMSS_SETTINGS_PATH="/app/settings.json" \
-e SESSION_SECRET="$(openssl rand -hex 32)" \
-e TZ=Europe/Paris \
jhmmt/pvmss:0.2.1The application will be available at http://localhost:50000.
-
Create
settings.json(see the configuration file) and secure it:chmod 600 settings.json
-
Create
docker-compose.yml:services: pvmss: image: jhmmt/pvmss:0.2.1 container_name: pvmss restart: unless-stopped ports: - "50000:50000/tcp" environment: PROXMOX_API_TOKEN_NAME: "tokenName@changeMe!value" PROXMOX_API_TOKEN_VALUE: "aaaaaaaa-0000-44aa-1111-aaaaaaaaaaa" PROXMOX_URL: "https://ip-or-name:8006/api2/json" PROXMOX_VERIFY_SSL: "false" ADMIN_PASSWORD_HASH: "$2y$10$Ppg7Wl3sNYrmxZmWgcq4reOyznt7AeqMrQucaH4HY.dBrzavhPP1e" LOG_LEVEL: "INFO" SESSION_SECRET: "changeMeWithSomethingElseUnique" PVMSS_ENV: "production" PVMSS_OFFLINE: "false" PVMSS_SETTINGS_PATH: "/app/settings.json" TZ: "Europe/Paris" volumes: - ./settings.json:/app/settings.json deploy: resources: limits: cpus: '1' memory: 64M
-
Start the stack:
docker compose up -d
-
Browse to http://localhost:50000.
-
Login with the admin credentials configured earlier, on the page "Login", click on "Administrator login".
Use the file pvmss-deployment.yaml to create namespace + secret + configmap + PVC + Deployment + Service.
Apply with kubectl apply -f pvmss-deployment.yaml. Provide your own ingress/HTTPRoute, an example is provided in pvmss-httproute.yml (Gateway API).
- Logs:
docker logs -f pvmssorkubectl -n pvmss logs -f deploy/pvmss. SwitchLOG_LEVEL=DEBUGfor verbose traces. - Health: startup logs include Proxmox connectivity, offline-mode status, and runtime metrics. The admin "Application Info" page shows runtime metrics, environment variables, and Proxmox cluster status.
- Upgrades: pull the desired image tag, update the file
settings.jsonif new fields appear, and restart the container.
- Security hardening is ongoing; no formal penetration test yet.
- Large clusters can make PVMSS slow or unresponsive, because of too many API calls and too many wait times.
- Cloud-Init support.
- OpenID Connect / SSO integration.
- Migration of VMs between Proxmox nodes.
- Advanced logging outputs (files, syslog shipping).
Feedback and contributions are welcome through issues or pull requests. Next versions and features will be documented here: https://github.com/julienhmmt/pvmss/projects?query=is%3Aopen.
PVMSS by Julien HOMMET is licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International. See https://creativecommons.org/licenses/by-nc-nd/4.0/.