Skip to main content
RunBook Academy

Proxmox VEXX · CLI & AutomationCLI

The PVE command surface, tool by tool

Intermediate⏱ ~30 minqmpctpvesmpvesh

What you'll learn

  • Name the tool that owns each area of a Proxmox node and its scope
  • Read the output of the core inspection commands and say what each column means
  • Choose between a specialised pve* tool and pvesh for the same operation
  • Collect evidence from a node with one command when opening a support case
  • Recognise which commands are node-scoped and which act cluster-wide

Prerequisites

Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12

Not yet marked complete on this device.

A Proxmox node ships roughly fifteen command-line tools, and the design is more consistent than it first appears: each tool owns one area of the system, and its name tells you which. Learning the map is worth more than memorising any individual command, because with the map you can find the command you need and without it you cannot.

The other thing worth knowing up front is that almost none of these tools do the work themselves. They are clients of the same REST API the web interface uses. That has practical consequences — for permissions, for what appears in the task log, and for what a script should call — and the mechanism section at the end covers them.

The map

ToolOwnsScope
qmQEMU/KVM virtual machinesThis node’s guests
pctLXC containersThis node’s guests
pvesmStorage definitions and volumesCluster-wide config, node-local status
pveshThe API itself, as a shellAnything the API exposes
pvecmCluster membership and quorumCluster-wide
pveumUsers, groups, roles, ACLs, API tokensCluster-wide
pvecephCeph deployment and lifecycleCluster-wide
pvenodeNode-level operations, tasks, certificatesThis node
ha-managerHA resources, groups and CRM commandsCluster-wide
pvesrStorage replication jobs (ZFS)Cluster-wide config
vzdumpTaking backupsThis node’s guests
qmrestoreRestoring a VM backupThis node
pvesubscriptionSubscription key and repository entitlementThis node
pveperfA quick node benchmarkThis node
pvereportEvidence collection for supportThis node
proxmox-boot-toolThe ESP, bootloader and kernel entriesThis node
pveversionPackage versionsThis node

The scope column is the one that catches people. qm and pct act on guests on the node you are logged into; pveum and pvecm change state that every node sees immediately. Running the wrong one on the wrong node is the difference between a mistake and an incident.

qm — virtual machines

Read-only / Safewhat VMs are on this node, and what is one of them made of?
qm list

VMID=100
qm config "$VMID"
qm status "$VMID" --verbose
Read-only / Safeqm list, and what the columns mean
# qm list
      VMID NAME                 STATUS     MEM(MB)    BOOTDISK(GB) PID
     100 db-primary           running    32768              500 2841
     101 web-01               running     8192               50 3012
     102 web-02               running     8192               50 3188
     141 reporting            running    16384              200 4402
     150 staging-old          stopped    16384              100 0

Illustrative output

The two qm subcommands that repay learning early are less obvious than start and stop.

Read-only / Safewhat QEMU command line does this configuration produce?
VMID=100
qm showcmd "$VMID" --pretty
Read-only / Safeqm showcmd tells you what PVE really did with your config
# qm showcmd 100 --pretty
/usr/bin/qemu-system-x86_64 \
-id 100 \
-name 'db-primary,debug-threads=on' \
-smp '8,sockets=1,cores=8,maxcpus=8' \
-cpu 'x86-64-v3,+aes,+pdpe1gb' \
-m 32768 \
-object 'iothread,id=iothread-virtioscsi0' \
-device 'virtio-scsi-pci,id=virtioscsi0,iothread=iothread-virtioscsi0' \
-drive 'file=/dev/zvol/rpool/data/vm-100-disk-0,if=none,id=drive-scsi0,\
cache=none,aio=io_uring,discard=on,format=raw' \
-machine 'type=pc-q35-10.0+pve0'

Illustrative output

Read-only / Safewhich disks does this VM own, and where do they live?
VMID=100
qm config "$VMID" | grep -E '^(scsi|virtio|sata|ide|efidisk|tpmstate)[0-9]*:'

pvesm list local-zfs --vmid "$VMID"

pct — containers

pct mirrors qm deliberately: list, config, start, stop, shutdown, status, set, destroy all behave the same way. Three subcommands have no qm equivalent because they exploit the fact that a container shares the host kernel.

Read-only / Safeget inside a container, and move files without a network
CTID=205

pct list
pct config "$CTID"

# a root shell inside, no SSH and no network required
pct enter "$CTID"
Configuration changecopy a file in or out without networking
CTID=205

pct push "$CTID" /root/fix.sh /root/fix.sh --perms 0755
pct pull "$CTID" /var/log/syslog /root/ct205-syslog

pct exec "$CTID" -- systemctl status nginx

pvesm — storage

Read-only / Safewhat storage exists, is it up, and what is on it?
pvesm status

pvesm list local-zfs
pvesm path local-zfs:vm-100-disk-0
Read-only / Safepvesm status, and the column that matters
# pvesm status
Name             Type     Status           Total            Used       Available        %
backup-pbs        pbs     active     41943040000     18294419456     23648620544   43.62%
ceph-rbd          rbd     active      8796093022      3221225472      5574867550   36.62%
local             dir     active        98564608        14203392        79322112   14.41%
local-zfs     zfspool     active      1717986918       412316860      1305670058   24.00%
nfs-iso           nfs   inactive               0               0               0    0.00%

Illustrative output

Storage entries have a content typeimages, rootdir, vztmpl, iso, backup, snippets, import — and a storage only accepts the types it declares. The documentation defines them as: images for “QEMU/KVM VM images”, rootdir to “allow to store container data”, vztmpl for “container templates”, backup for “backup files (vzdump)”, iso for “ISO images”, snippets for “snippet files, for example guest hook scripts”, and import for “OVAs and VM disk images that can be imported from this storage”.

pvesh — the API as a shell

pvesh is “a shell interface for the Proxmox VE API” that, in the man page’s words, “allows to directly invoke API function, without using the REST/HTTPS server”. Five subcommands map onto HTTP methods:

pveshHTTPUse
getGETRead
setPUTModify an existing object
createPOSTCreate, or invoke an action
deleteDELETERemove
lsList child nodes of a path
usagePrint the API documentation for a path
Read-only / Safeexplore the API without leaving the shell
pvesh ls /nodes
pvesh ls /cluster

pvesh usage /nodes/{node}/qemu/{vmid}/status/start --verbose
Read-only / Safethe single most useful pvesh call
pvesh get /cluster/resources --type vm --output-format json | jq -r \
'.[] | [.vmid, .name, .node, .status] | @tsv'
Read-only / Safeevery guest in the cluster, and where it is
# pvesh get /cluster/resources --type vm --output-format json | jq -r '.[] | [.vmid, .name, .node, .status] | @tsv'
100	db-primary	pve-01	running
101	web-01	pve-01	running
102	web-02	pve-02	running
141	reporting	pve-03	running
205	dns-01	pve-02	running
150	staging-old	pve-02	stopped

Illustrative output

--output-format accepts json, json-pretty, text and yaml, with text as the default. Scripts should always pass json: the text format is a human-readable table whose columns can change between versions, and parsing it is how automation breaks at an upgrade.

pvecm — cluster membership

Read-only / Safeis this node in the cluster, and does the cluster have quorum?
pvecm status
pvecm nodes
Read-only / Safepvecm status on a healthy three-node cluster
# pvecm status
Cluster information
-------------------
Name:             pve-prod
Config Version:   7
Transport:        knet
Secure auth:      on

Quorum information
------------------
Date:             Wed Aug 12 14:31:08 2026
Quorum provider:  corosync_votequorum
Nodes:            3
Node ID:          0x00000001
Ring ID:          1.4f2
Quorate:          Yes

Votequorum information
----------------------
Expected votes:   3
Highest expected: 3
Total votes:      3
Quorum:           2
Flags:            Quorate

Illustrative output

pveum — access control

Read-only / Safewho has access to what?
pveum user list
pveum role list
pveum acl list
pveum token list root@pam
Configuration changecreate a scoped automation identity
pveum user add automation@pve --comment "CI pipeline"
pveum acl modify /vms/100 --users automation@pve --roles PVEVMAdmin
pveum user token add automation@pve ci --privsep 1

pveum acl list

pvenode — the node itself

pvenode is the tool most operators discover last and then use daily, because it owns the task log.

Read-only / Safewhat has this node been doing?
pvenode task list --limit 20

pvenode config get
pvenode cert info
Read-only / Safepvenode task list, with a failure in it
# pvenode task list --limit 6
UPID                                                       Type       Status
UPID:pve-01:00006A2F:04C1B2E1:6A7C83E0:vzdump:100:root@pam: vzdump     OK
UPID:pve-01:00006B41:04C2F011:6A7BD3F1:vzdump:101:root@pam: vzdump     OK
UPID:pve-01:00006C88:04C41A02:6A7BD3A3:vzdump:141:root@pam: vzdump     job errors
UPID:pve-01:00007012:04C88811:6A7C2A18:qmigrate:102:root@pam: qmigrate OK
UPID:pve-01:000071A0:04C9C401:6A7C3B04:qmstart:150:root@pam: qmstart   OK
UPID:pve-01:00007244:04CA1180:6A7C4D90:qmsnapshot:100:root@pam: qmsnapshot OK

Illustrative output

Service impact possiblebulk guest operations for a maintenance window
TARGET=pve-02

pvenode migrateall "$TARGET" --maxworkers 2

# after maintenance
pvenode startall

ha-manager, pvesr, pveceph

Read-only / Safewhat is HA managing, and what does the CRM think?
ha-manager status
ha-manager config
Read-only / Safereplication and Ceph status
pvesr status
pvesr list

pveceph status
pveceph pool ls

Backup, restore and evidence

Service impact possibletake a backup by hand
VMID=100

vzdump "$VMID" --storage backup-pbs --mode snapshot --bwlimit 102400 --notes-template '{{guestname}} manual'
Destructiverestore a VM from a backup
NEWID=900
qmrestore /var/lib/vz/dump/vzdump-qemu-100-2026_08_12-02_00_03.vma.zst "$NEWID" --storage local-zfs

qm config "$NEWID"
Read-only / Safecollect everything at once for a support case
pvereport > "/root/pvereport-$(hostname)-$(date +%F).txt"

wc -l "/root/pvereport-$(hostname)-$(date +%F).txt"
Read-only / Safeversions, subscription and boot configuration
pveversion -v
pvesubscription get
proxmox-boot-tool status

Which tool answers which question?

The questionThe command
What is on this node?qm list, pct list
Where in the cluster is guest N?pvesh get /cluster/resources --type vm
Why did last night’s backup fail?pvenode task list, then pvenode task log UPID
Is the cluster quorate?pvecm status
Is the storage reachable?pvesm status
What can this user actually do?pveum acl list
Did my disk option reach QEMU?qm showcmd VMID --pretty
What is HA about to do?ha-manager status
What do I attach to a support case?pvereport, pveversion -v
Where do kernel parameters go on this node?proxmox-boot-tool status
What parameters does this API path take?pvesh usage PATH --verbose

Common mistakes

  • Treating qm list as a cluster view. It shows one node. pvesh get /cluster/resources --type vm is the cluster inventory.
  • Parsing pvesh text output in a script. It is a human table. Always pass --output-format json.
  • Using qm stop when qm shutdown was meant. stop is the power cable; shutdown sends ACPI and lets the guest flush its filesystems.
  • pvesm set --content without listing every type you want. The option replaces the list; omitting a type removes it.
  • Reaching for pvecm expected 1 during a quorum loss. It is a recovery tool for nodes you have confirmed are powered off, not a first response to a partition.
  • Restoring onto an existing VMID. qmrestore overwrites it, including disks, without a prompt.
  • Running pvereport after rebooting the node. Collect the evidence while the fault is present.
  • Not knowing which bootloader the node uses. proxmox-boot-tool status answers it; guessing means editing a file nothing reads.

Key takeaways

  • Each tool owns one area, and its name says which. Learn the map, not the commands.
  • qm and pct are node-scoped; pvecm, pveum, pveceph and ha-manager change cluster-wide state that propagates immediately.
  • pvesh is the API as a shell, with get/set/create/delete mapping to GET/PUT/POST/DELETE, plus ls and usage for exploring.
  • pvesh get /cluster/resources is the cluster-wide inventory that qm list is not.
  • pvenode task list and pvenode task log are where you find out what happened overnight.
  • qm showcmd --pretty proves whether a configuration option actually reached QEMU.
  • Storage entries declare content types; “does not support content type” is configuration, not a bug, and pvesm set --content replaces the list rather than appending to it.
  • pvereport collects everything a support case needs, and should be run while the fault is still present.
  • Every pve* tool is a client of the same API with the same permission checks, so scripts should call documented API paths with JSON output rather than parse human-formatted tables.

Knowledge check

Knowledge check · 5 questions

  1. Q1. After an HA failover you need to know which node VM 141 is running on, from a shell on pve-01. Which command answers it?

  2. Q2. Which of these commands change state that every node in the cluster sees immediately? Select all that apply.

  3. Q3. pvesh talks to the API without going through the REST/HTTPS server, so it also bypasses the API permission checks and always runs with full privileges.

  4. Q4. A vzdump job fails with an error saying the storage does not support content type "backup". What is the fix?

  5. Q5. Why should a durable automation script call pvesh with --output-format json rather than parsing the default output?

Passing score: 75%. Answers are checked in this browser.