Proxmox Permissions (Least Privilege)¶
Exactly which PVE privileges the panel needs, per feature — and how to grant them without handing over the farm.
Privilege matrix¶
| Feature (panel side) | PVE privilege(s) | Used for |
|---|---|---|
| Connection test, version read | (none beyond a valid token) | GET /version works for any authenticated token. |
| Node discovery + node sync | Sys.Audit |
GET /nodes, GET /nodes/{n}/status. |
| VM discovery + import + instance sync + metrics | VM.Audit |
GET /cluster/resources?type=vm, GET /nodes/{n}/qemu, GET …/status/current. |
| Storage discovery/mapping | Datastore.Audit |
GET /storage, GET /nodes/{n}/storage. |
| Network/template discovery | Sys.Audit / VM.Audit |
GET /nodes/{n}/network; templates ride the VM resource list. |
| Power actions | VM.PowerMgmt |
POST …/qemu/{vmid}/status/{cmd}. |
| Task (UPID) polling | covered by the audits above | GET /nodes/{n}/tasks/{upid}/status. |
| Future — VM creation | VM.Allocate + Datastore.AllocateSpace |
POST /nodes/{n}/qemu, disk allocation. |
| Future — snapshots | VM.Snapshot |
Snapshot create/rollback/delete. |
| Future — migration | VM.Migrate |
POST …/migrate. |
| Future — console | VM.Console |
VNC/serial ticket. |
Not needed today (do not grant): VM.Config.*, VM.Backup,
Datastore.Allocate, Realm.Allocate*, Permissions.Modify, anything
Sys.Modify-adjacent.
Suggested role¶
pveum role add PteroCloud -privs "VM.Audit VM.PowerMgmt Datastore.Audit Sys.Audit"
pveum user add pterocloud@pve --comment "PteroCloud panel integration"
pveum acl modify / --users pterocloud@pve --roles PteroCloud
pveum user token add pterocloud@pve panel --privsep 0
Notes:
--privsep 0(no privilege separation): the token inherits the user's ACLs exactly, so thePteroCloudrole remains the single place to reason about. With--privsep 1you must maintain privileges twice.- Path scoping narrows the blast radius: grant the role on
/nodes/<node>(+/storage/<id>) to confine the panel to one node, or on/vms/<vmid>for a single guest. Discovery is cluster-shaped, so a scoped token shows a partial inventory; the connection test reports that as failed steps, which is expected for a deliberately scoped token. - Read-only panels can drop
VM.PowerMgmtand should also set the panel-sideread_onlyflag.
Why not root@pam¶
- A
root@pamtoken is total: it can delete VMs, alter cluster membership, change authentication realms, and read every guest's config. - The panel stores token secrets (encrypted, but they exist to be used). Least privilege means a leaked or misused secret can enumerate and power-cycle VMs — and nothing else.
- PVE API tokens are revocable independently of the user, so rotation does not touch any human's credentials.
- Auditability: PVE task history attributes every action to
pterocloud@pve!panel, never to a person.
How gaps surface¶
The panel surfaces gaps without failing hard: the connection test's permission
inspector runs read-only probes and reports granted[]/missing[]/warnings[]
— e.g. a missing VM.PowerMgmt shows up as a warning at test time instead of a
surprise 403 on a customer's restart. Only an explicit 403 (or a readable
permission map lacking the privilege) counts as "missing"; inconclusive probes
become warnings.