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.
Every storage lesson that follows — ZFS, Ceph, NFS, iSCSI — is about a
technology. This one is about the layer Proxmox VE puts in front of all of them,
and it is the layer you actually operate.
When a backup fails with “storage does not support content type”, when a
migration refuses to start, when a disk lands somewhere you did not expect, the
answer is almost never in the storage technology. It is in the eight lines of
storage.cfg that describe it.
The file
Storage configuration lives in /etc/pve/storage.cfg and is therefore cluster
configuration: written once, present on every node, and covered by the same
quorum rules as everything else in /etc/pve. Its format is deliberately plain:
dir: local path /var/lib/vz content iso,vztmpl,backup prune-backups keep-last=3lvmthin: local-lvm thinpool data vgname pve content rootdir,imagesrbd: shared-rbd content images,rootdir krbd 0 pool vm-poolpbs: pbs-primary datastore main server 192.0.2.20 content backup fingerprint aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99 prune-backups keep-daily=14,keep-weekly=8,keep-monthly=6nfs: iso-share export /export/isos server 192.0.2.30 content iso,vztmpl nodes pve-a1,pve-a2,pve-a3 options vers=4.2
Five entries, five different backends, one grammar. That uniformity is the
point of the abstraction: qm, pct, vzdump, the GUI and the API all speak
to a storage through the same interface regardless of what is underneath.
Type: what is underneath
The type is the plugin. It determines the storage’s capabilities, and the
documentation divides the plugins into two classes that predict most of the
behaviour you will meet.
File-level — ZFS (as a filesystem), Directory, BTRFS, NFS, CIFS, CephFS.
POSIX filesystems, so they can hold any content type, including ISO images,
container templates, backups and snippets. Disk images on them are files:
qcow2, raw or vmdk.
Block-level — LVM, LVM-thin, iSCSI, Ceph/RBD, ZFS zvols. They hold raw
volumes and nothing else, so a block storage cannot store an ISO or a backup
file.
The content property is a comma-separated list, and it is enforced. The seven
content types:
Content type
Holds
images
QEMU/KVM virtual machine disks
rootdir
Container root filesystems
vztmpl
Container templates
iso
ISO images
backup
vzdump backup files
snippets
Guest hook scripts and Cloud-Init snippets
import
OVAs and disk images staged for import
Read-only / Safewhat each storage is, holds and has left— Read-only. pvesm status is the single most useful storage command: it shows type, status, total, used and available for every configured storage, with the active/enabled state that explains a storage the GUI is showing in grey.
pvesm status
pvesm status --content images
pvesm list local-lvm
Read-only / Safe
$ pvesm status
Name Type Status Total Used Available %
iso-share nfs active 524288000 31457280 492830720 6.00%
local dir active 100663296 8388608 92274688 8.33%
local-lvm lvmthin active 1932735283 772294113 1160441170 39.96%
pbs-primary pbs active 10737418240 4294967296 6442450944 40.00%
shared-rbd rbd active 32212254720 9663676416 22548578304 30.00%
Node restriction, and the shared flag
Two properties that look similar and mean very different things.
nodes restricts which cluster nodes may access this storage. It is an
access-control statement about topology: an NFS export reachable only from the
management VLAN, or a local storage that exists on three nodes and not the
fourth. Guests using a node-restricted storage cannot be migrated to a node
outside the list.
shared tells PVE that every node sees the same data on this storage. It
is the flag that makes live migration cheap — with shared storage, migrating a
running VM moves memory and leaves the disks in place.
The volume identifier
Every guest disk is named by a volume ID, storage:volume, and this is what
appears in a guest configuration:
Read the second one carefully: on a file-level storage the volume part includes
the VMID directory and the file extension, because it is a path relative to the
storage. On a block-level storage it is just a volume name, because there is no
directory structure to reference.
The storage ID is the first field, which has a consequence worth internalising:
a guest’s disk is bound to a storage ID, not to a device. Rename a storage
and every guest referencing it breaks. Point a storage ID at different hardware
and every guest referencing it silently follows.
Read-only / Saferesolve a volume ID to a path or device— Read-only. pvesm path turns a volume ID into the filesystem path or block device the node will actually open. This is the fastest way to answer 'where is this disk really' and to prove that two nodes resolve the same volume differently.
Volid Format Type Size VMID
shared-rbd:vm-141-disk-0 raw images 68719476736 141
shared-rbd:vm-141-disk-1 raw images 536870912000 141
Adding a storage properly
Configuration changeadd an NFS storage restricted to three nodes— Changes cluster configuration. pvesm add validates the type and property names and writes through pmxcfs, so the entry appears on every node atomically. The storage is created enabled; add --disable 1 to stage it.
Configuration changechange a content list safely— Changes cluster configuration. --content REPLACES the existing list. Read the current value first, then write the full intended list. Removing a content type that existing volumes rely on makes those volumes unusable without deleting them.
pvesm status --storage local | cat
grep -A6 '^dir: local$' /etc/pve/storage.cfg
pvesm set local --content iso,vztmpl,backup,snippets
Key takeaways
/etc/pve/storage.cfg is cluster configuration: <type>: <ID> followed by
indented properties, identical grammar for every backend.
The type is the plugin and it determines capability. File-level backends
(dir, nfs, cifs, cephfs, btrfs, zfspool as a filesystem) hold any
content type; block-level backends (lvm, lvmthin, iscsi, rbd) hold raw
volumes only.
content is enforced. “Does not support content type” means the backend
cannot hold it, or the list does not include it. pvesm set --contentreplaces the list.
nodes restricts where a storage may be used and constrains migration.
shared asserts that every node sees the same data.
shared 1 on a storage that is not genuinely shared causes silent data
divergence during migration. Set it only where the backend shares: NFS,
CIFS, CephFS, RBD, or LVM on a shared LUN.
A volume ID is storage:volume, and a guest is bound to the storage ID.
File-level volumes carry the VMID directory and an extension; block-level
volumes do not.
pvesm status for capacity and activation, pvesm list for volumes,
pvesm path to resolve a volume to a device, pvesm alloc/free to create
and destroy. Check status on more than one node.
Removing a storage entry breaks references but keeps data and is recoverable
by re-adding it. Freeing a volume is not.
Knowledge check
Knowledge check · 5 questions
Q1. Each node has a directory storage with the same path, backed by that node local disks. Someone sets shared 1 so that live migration works. What actually happens on the first migration?
Q2. A backup job fails with "storage does not support content type". The target is an LVM-thin storage. What is the correct fix?
Q3. Which statements about volume identifiers are correct? Select all that apply.
Q4. Running pvesm remove on a storage that still holds guest disks deletes those disks.
Q5. A storage shows as active on pve-a1 but inactive on pve-a2, and the storage.cfg entry is identical because it is cluster configuration. How is that possible?
Passing score: 75%. Answers are checked in this browser.