Skip to content

Proxmox API Token Setup (labctl)

Instructions for creating a Proxmox VE API token with the permissions labctl needs to audit and interrogate VMs and LXCs.

Current Token

The existing PVE_TOKEN_ID / PVE_TOKEN_SECRET in .env can read VM/LXC configs, resources, storage, and network info. It cannot execute commands inside guests.

What the New Token Enables

  • VM.GuestAgent.Unrestricted — execute arbitrary commands via QEMU guest agent on VMs that have agent: 1 (saltierpoop, infra-services, haos, metrimon, etc.)
  • VM.GuestAgent.Audit + VM.GuestAgent.FileRead — informational guest agent commands and file reads (subset of Unrestricted)
  • This lets labctl run cat /etc/os-release, systemctl list-units, df -h, docker ps, etc. inside VMs without SSH.
  • For LXCs, pct exec requires root-level Proxmox access which is not recommended for an API token. LXC interrogation should use SSH.

Steps

1. Create a custom role

In the Proxmox UI: Datacenter > Permissions > Roles > Create

Field Value
Role ID LabctlAudit
Privileges VM.Audit, VM.GuestAgent.Unrestricted, VM.GuestAgent.Audit, VM.GuestAgent.FileRead, Sys.Audit, Datastore.Audit, Pool.Audit

Or via CLI on prox:

pveum role add LabctlAudit -privs "VM.Audit,VM.GuestAgent.Unrestricted,VM.GuestAgent.Audit,VM.GuestAgent.FileRead,Sys.Audit,Datastore.Audit,Pool.Audit"

2. Create a user (if not reusing an existing one)

pveum user add labctl@pve

3. Assign the role

Grant LabctlAudit at the root path (/) so the token can see all nodes, VMs, and LXCs:

pveum acl modify / -user labctl@pve -role LabctlAudit

4. Create an API token

pveum user token add labctl@pve audit --privsep=0

--privsep=0 means the token inherits the user's permissions directly (no separate token-level ACL). The command outputs:

┌──────────────┬──────────────────────────────────────┐
│ key          │ value                                │
╞══════════════╪══════════════════════════════════════╡
│ full-tokenid │ labctl@pve!audit                     │
├──────────────┼──────────────────────────────────────┤
│ info         │ {"privsep":"0"}                      │
├──────────────┼──────────────────────────────────────┤
│ value        │ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │
└──────────────┴──────────────────────────────────────┘

Save the value immediately — it is only shown once.

5. Update .env

Replace or add these values in the project .env:

PVE_TOKEN_ID=labctl@pve!audit
PVE_TOKEN_SECRET=<the value from step 4>

6. Verify

uv run python scripts/labctl/__main__.py proxmox vms

Should return the VM list as before. To test guest agent access, we'll add a new labctl proxmox exec <vmid> <command> subcommand once the token is working.

Privilege Reference

Privilege What it does
VM.Audit Read VM/LXC config, status, snapshots
VM.GuestAgent.Unrestricted Execute arbitrary commands via QEMU guest agent (guest-exec)
VM.GuestAgent.Audit Informational guest agent queries (network, OS info, etc.)
VM.GuestAgent.FileRead Read files from guest filesystem via guest agent
Sys.Audit Read node status, syslog, task log
Datastore.Audit Read storage status and content lists
Pool.Audit Read pool membership

Security Notes

  • This token has read-only + guest-agent-exec access. It cannot create, modify, start, stop, or delete any VM/LXC.
  • VM.GuestAgent.Unrestricted can run arbitrary commands inside VMs with agent: 1. Treat the token secret like an SSH key.
  • Store the token in .env (gitignored) and/or SOPS-encrypt for CI.