Files
agent-skills/skills/proxmox-admin/references/command-reference.md
T
MalinandClaude Sonnet 5 1d24660303 skills(wordpress-plugin-conventions): merge security/lifecycle checks from wordpress/agent-skills
Per the 2026-08-15 skills.sh and autoskills.sh scans, both flagged
wordpress/agent-skills' wp-plugin-development module (Automattic-origin,
now WordPress-org-hosted) as high-value source material for iWP's plugin
skill: nonce+capability dual-check discipline, late escaping, prepared
SQL, cron idempotency, and uninstall-vs-deactivation guardrails.

Adapted (not copied) against real iWP plugin code in wp-plugins/:
- nonce+capability must-both framing, cited against
  class-iwp-cache-db-cleanup.php's actual AJAX handler
- late-escaping and wp_unslash()/explicit-key superglobal reading
- %i identifier-placeholder version gate (WP 6.2+, most iWP plugins
  floor at 6.0 or lower)
- new "Admin settings" section documenting the real Settings-API vs.
  AJAX-dashboard split across the suite, since the source's generic
  Settings-API-first prescription doesn't match roughly half of iWP's
  plugins
- new cron idempotency section citing the existing wp_next_scheduled()
  guard already used consistently in iwp-cache/iwp-woosales/iwp-booking
- new uninstall-vs-deactivation section flagging that only 3 of ~15
  plugins ship uninstall.php despite most creating options/tables
- new release-packaging checklist tied to iWP's actual IWP_Updater
  version-wiring convention (header/constant/updater param must agree)

Provenance noted inline with source URL. Left out the source's generic
architecture/Settings-API prescription and its detect_plugins.mjs
script (skill's house style is prose-only, no bundled scripts).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 21:26:46 +02:00

12 KiB

Proxmox CLI command reference

Full command coverage for qm, pct, pvesm, pvecm, pveam, backup/ restore, networking, firewall, and troubleshooting. Adapted from bastos/skills@proxmox-admin (upstream source: see SKILL.md provenance note) with all example VMIDs, storage pool names, bridge names, and networks replaced by placeholders — none of the values below are this fleet's real values. Resolve real values from docs/server-*.md or from live discovery (qm list, pvesm status, etc.) before running anything.

Read SKILL.md first — it has the safety workflow and the destructive- command tier list this reference assumes you already know. Everything in a "never run without confirmation" tier there is repeated here only as reference syntax, not as something to execute unattended.

Tool overview

Tool Purpose
qm Manage KVM virtual machines
pct Manage LXC containers
pvesm Manage storage
pvecm Manage cluster
pveam Manage appliance/template downloads
pvesh Access the Proxmox API from the shell
pveperf Benchmark host performance

VM management with qm

Creating a VM (destructive tier: creates persistent state — confirm first)

qm create <vmid> --name <vm-name> --memory 2048 --cores 2 --sockets 1 \
  --net0 virtio,bridge=<bridge> --ostype l26

# SCSI disk on a given storage pool
qm create <vmid> --name <vm-name> --memory 4096 --cores 4 \
  --scsi0 <storage>:32 --scsihw virtio-scsi-pci \
  --net0 virtio,bridge=<bridge> --ostype l26

# Attach an ISO for installation
qm set <vmid> --cdrom <storage>:iso/<image>.iso --boot order=ide2

VM lifecycle

Command Purpose Tier
qm start <vmid> Start a VM generally fine once target confirmed
qm shutdown <vmid> Graceful ACPI shutdown generally fine
qm stop <vmid> Force stop (like pulling power) confirm first — no ACPI grace
qm reboot <vmid> Reboot (ACPI-graceful) can hang if guest unresponsive — see SKILL.md
qm reset <vmid> Hard reset confirm clean unmount first — see SKILL.md
qm suspend <vmid> Suspend to RAM confirm first
qm resume <vmid> Resume from suspend generally fine
qm destroy <vmid> Delete VM and its disks never without human confirmation
qm destroy <vmid> --purge Delete VM, disks, and all related jobs never without human confirmation

VM configuration

qm config <vmid>                     # show current config — always run before qm set

qm set <vmid> --memory 8192
qm set <vmid> --cores 4
qm set <vmid> --balloon 2048          # dynamic memory (min)
qm set <vmid> --cpu cputype=host      # pass through host CPU features
qm set <vmid> --machine q35           # Q35 chipset (needed for PCIe passthrough)

# Add/resize disks — check pvesm status for free space first
qm set <vmid> --scsi1 <storage>:50    # add a 50GB disk
qm disk resize <vmid> scsi0 +20G      # grow an existing disk

# Networking — <bridge> and any VLAN tag are fleet-specific, resolve first
qm set <vmid> --net0 virtio,bridge=<bridge>,tag=<vlan>
qm set <vmid> --net1 virtio,bridge=<bridge2>

# Cloud-init
qm set <vmid> --ide2 <storage>:cloudinit
qm set <vmid> --ciuser <user> --cipassword '<generated-secret>'
qm set <vmid> --ipconfig0 ip=<ip>/<cidr>,gw=<gateway>
qm set <vmid> --sshkeys ~/.ssh/authorized_keys
qm set <vmid> --boot order=scsi0

# EFI / UEFI boot
qm set <vmid> --bios ovmf --efidisk0 <storage>:1,efitype=4m,pre-enrolled-keys=1

# Serial console (headless)
qm set <vmid> --serial0 socket --vga serial0

# PCI passthrough
qm set <vmid> --hostpci0 <pci-address>,pcie=1

Snapshots and cloning

See SKILL.md's "Snapshot vs. backup" section before relying on any of these as your only safety net.

qm snapshot <vmid> <snapshot-name> --description "<why>"
qm listsnapshot <vmid>
qm rollback <vmid> <snapshot-name>
qm delsnapshot <vmid> <snapshot-name>

qm clone <vmid> <new-vmid> --name <new-name> --full   # full copy
qm clone <vmid> <new-vmid> --name <new-name>            # linked clone (shares base disk)

Templates

qm template <vmid>    # convert VM to template — IRREVERSIBLE, confirm first

qm clone <template-vmid> <new-vmid> --name <new-name>          # linked clone from template
qm clone <template-vmid> <new-vmid> --name <new-name> --full   # full clone from template

Migration (confirm first — affects a second node)

qm migrate <vmid> <target-node> --online   # online (live) migration
qm migrate <vmid> <target-node>            # offline migration

Monitoring

qm status <vmid>
qm list

qm agent <vmid> ping
qm agent <vmid> get-osinfo

qm monitor <vmid>     # QEMU monitor console

Container management with pct

Creating a container (destructive tier — confirm first)

# Download a template first
pveam update
pveam available --section system
pveam download <storage> <template-filename>

pct create <ctid> <storage>:vztmpl/<template-filename> \
  --hostname <ct-name> --memory 1024 --cores 2 \
  --rootfs <storage>:8 \
  --net0 name=eth0,bridge=<bridge>,ip=dhcp \
  --password '<generated-secret>' --unprivileged 1

# Static IP variant
pct create <ctid> <storage>:vztmpl/<template-filename> \
  --hostname <ct-name> --memory 2048 --cores 2 \
  --rootfs <storage>:16 \
  --net0 name=eth0,bridge=<bridge>,ip=<ip>/<cidr>,gw=<gateway> \
  --nameserver <dns-ip> --unprivileged 1

Container lifecycle

Command Purpose Tier
pct start <ctid> Start container generally fine once target confirmed
pct shutdown <ctid> Graceful shutdown generally fine
pct stop <ctid> Force stop confirm first
pct reboot <ctid> Reboot container same ACPI-hang caveat as qm reboot
pct destroy <ctid> Delete container and its volumes never without human confirmation
pct enter <ctid> Open a shell inside the container generally fine
pct exec <ctid> -- <cmd> Run a command inside the container depends what <cmd> does
pct console <ctid> Attach to container console generally fine

Container configuration

pct config <ctid>                     # always run before pct set

pct set <ctid> --memory 4096
pct set <ctid> --cores 4
pct set <ctid> --swap 1024

pct set <ctid> --mp0 /mnt/data,mp=/data              # bind mount from host
pct set <ctid> --mp1 <storage>:50,mp=/var/lib/data   # additional storage volume

pct set <ctid> --net0 name=eth0,bridge=<bridge>,ip=<ip>/<cidr>,gw=<gateway>
pct set <ctid> --net1 name=eth1,bridge=<bridge2>,ip=dhcp

pct set <ctid> --features nesting=1
pct set <ctid> --features nesting=1,fuse=1,mount=nfs

pct set <ctid> --nameserver "<dns-ip-1> <dns-ip-2>" --searchdomain <domain>

pct set <ctid> --onboot 1 --startup order=1,up=30

Container snapshots and cloning

pct snapshot <ctid> <snapshot-name>
pct rollback <ctid> <snapshot-name>
pct clone <ctid> <new-ctid> --hostname <new-name> --full

Storage management

pvesm status                  # list pools + free space — check before any restore/resize

pvesm list <storage>          # content of a specific storage pool

# Adding storage is a cluster-wide config mutation — confirm first
pvesm add dir <name> --path <path> --content backup
pvesm add nfs <name> --server <nfs-server-ip> --export <export-path> --content images,vztmpl
pvesm add lvm <name> --vgname <vg-name> --content rootdir,images
pvesm add zfspool <name> --pool <zfs-pool>/<dataset> --content rootdir,images

pvesm remove <name>           # never without human confirmation

wget -P /var/lib/vz/template/iso/ <iso-url>

Networking

cat /etc/network/interfaces     # current bridge/interface config — read first

# Bridge stanza shape (values are placeholders, not this fleet's real config)
# auto <bridge>
# iface <bridge> inet static
#     address <host-ip>/<cidr>
#     bridge-ports <physical-nic>
#     bridge-stp off
#     bridge-fd 0

ifreload -a     # apply network changes — can drop connectivity if misconfigured, confirm first

Cluster management (all tiers below: confirm first — affects multiple nodes)

pvecm create <cluster-name>
pvecm add <existing-cluster-node-ip>
pvecm status
pvecm nodes
pvecm delnode <node-name>
pvecm expected 1     # force quorum — single-node recovery only, real split-brain risk otherwise

Firewall

pve-firewall start
pve-firewall stop
pve-firewall status

# Datacenter:  /etc/pve/firewall/cluster.fw   ([OPTIONS] enable: 1)
# Node:        /etc/pve/nodes/<node>/host.fw
# VM/CT:       /etc/pve/firewall/<vmid>.fw
#
# Add remote-management allow rules BEFORE enabling a restrictive default
# policy — locking yourself out of remote access to the node is a real,
# hard-to-recover-from failure mode.

Backup and restore

vzdump <vmid> --storage <backup-storage> --mode snapshot --compress zstd
vzdump <ctid> --storage <backup-storage> --mode stop --compress zstd
vzdump --all --storage <backup-storage> --mode snapshot --compress zstd --mailto <admin-email>

# Restore — never without human confirmation (creates/overwrites a guest).
# Check pvesm status for target free space FIRST, especially for large disks.
qmrestore <path-to-vzdump-file> <vmid> --storage <storage>
pct restore <ctid> <path-to-vzdump-file>

Common provisioning patterns (reference only — each step still follows the tier rules above)

Cloud-init VM from a template

qm template <base-vmid>                                    # irreversible — confirm first

qm clone <base-vmid> <new-vmid> --name <new-name> --full
qm set <new-vmid> --ciuser <user> --sshkeys ~/.ssh/authorized_keys
qm set <new-vmid> --ipconfig0 ip=<ip>/<cidr>,gw=<gateway>
qm set <new-vmid> --nameserver <dns-ip>
qm start <new-vmid>

Note: some Proxmox documentation and community examples use VMIDs like 9000 as a convention for template base images. That's a naming convention some operators adopt, not a Proxmox default or a value to copy into this fleet — check docs/server-*.md for whatever convention (if any) applies to a given host before picking an ID.

Batch-create containers

Bulk/loop patterns are explicitly a higher tier than the single-target equivalent (see SKILL.md) — pilot one iteration manually, confirm it's correct, before running the loop.

for i in $(seq 1 <count>); do
  CTID=$((<base-ctid> + i))
  pct create "$CTID" <storage>:vztmpl/<template-filename> \
    --hostname "<name-prefix>-${i}" --memory 1024 --cores 2 \
    --rootfs <storage>:8 \
    --net0 name=eth0,bridge=<bridge>,ip=<ip-prefix>.$((<ip-offset> + i))/<cidr>,gw=<gateway> \
    --unprivileged 1 --start 1
done

Import a disk image (e.g. a cloud image)

wget <cloud-image-url>

qm disk import <vmid> <downloaded-image-file> <storage>
qm set <vmid> --scsi0 <storage>:vm-<vmid>-disk-0
qm set <vmid> --boot order=scsi0

Troubleshooting

Problem Solution
VM won't start qm config <vmid>, verify storage exists with pvesm status
"TASK ERROR: can't lock file" Check for a genuinely running task first; if the task is gone, qm unlock <vmid> / pct unlock <ctid>
Container has no network Check bridge exists: brctl show; verify firewall rules
Disk full on storage pvesm status for usage; lvs for LVM thin pools
Cluster quorum lost pvecm expected 1 on a surviving node — single-node recovery only, confirm first
Migration fails Check CPU type compatibility; confirm network reachability between nodes
Backup fails with lock error qm unlock <vmid> / pct unlock <ctid>
Slow disk I/O in VM --scsihw virtio-scsi-single plus disk options like ,iothread=1,discard=on
Guest agent not responding Install qemu-guest-agent in the guest, then qm set <vmid> --agent 1
SSH/command seems to hit the wrong host See SKILL.md's Tailscale hostname-collision gotcha — verify with ssh -v <host> 2>&1 | grep "Connecting to"

Useful paths

Path Contents
/etc/pve/ Cluster-wide config (pmxcfs)
/etc/pve/qemu-server/<vmid>.conf VM configuration files
/etc/pve/lxc/<ctid>.conf Container configuration files
/etc/pve/storage.cfg Storage definitions
/etc/pve/nodes/ Per-node configuration
/var/lib/vz/ Default local storage root
/var/lib/vz/template/iso/ ISO images
/var/lib/vz/template/cache/ Container templates
/var/lib/vz/dump/ Backup files
/var/log/pve/tasks/ Task logs