Proxmox VE VM Storage: Choosing Between ZFS, LVM-thin, and Ceph RBD
A decision guide to picking a Proxmox VE storage backend for VM images: how ZFS, LVM-thin, and Ceph RBD differ, plus a corrected ZFS mirror setup and validation steps.
29 Jan 2026, 22:54 UTC

The decision and its constraints
Proxmox VE ships several storage plugins, and the one you choose for VM disk images determines snapshot behavior, replication options, memory overhead, and how much work a second node will be. The three backends most often compared for guest images are ZFS, LVM-thin, and Ceph RBD (RADOS Block Device — a block device served by a Ceph cluster).
The constraints that usually decide it: one node or several, how much RAM you can spare, whether you need copies of guest data on another machine, and whether you want storage you can operate without a second system to maintain.
Commands and GUI paths below assume Proxmox VE 8.x. Plugin names, GUI labels, and defaults change between releases, so confirm option names against the storage documentation for your installed version before applying anything. Unless stated otherwise, run commands as root on a PVE node.
Supported options at a glance
| Feature | ZFS | LVM-thin | Ceph RBD |
|---|---|---|---|
| Snapshots | Native copy-on-write, exposed in the GUI | Thin snapshots, exposed in the GUI | RBD snapshots, exposed in the GUI |
| Integrity checking | Checksums on all data; a scrub can repair from a mirror or RAIDZ vdev | None at the storage layer; silent corruption is not detected | Per-OSD checksums, scrub and self-heal across replicas |
| Inline compression | Yes, a per-dataset property | No | Not offered by the Proxmox plugin; Ceph can compress at the OSD level if configured (version-dependent — verify for your release) |
| Cross-node replication | Proxmox VE storage replication for ZFS-backed guests; also manual zfs send/receive |
None built in | Data is replicated by the cluster itself; RBD mirroring to a remote cluster is a separate Ceph feature with its own prerequisites |
| Nodes needed for redundancy | Two or more disks for a mirror; local to one node | Local only; rely on RAID below LVM | Three or more nodes for a meaningful cluster |
| Operational overhead | Moderate — ARC tuning, scrub scheduling | Low — standard LVM tooling | High — a Ceph cluster to deploy and monitor |
Trade-offs that change the answer
- ZFS gives the strongest integrity story on a single node and adds compression for free. The cost is memory: the ARC (Adaptive Replacement Cache) uses RAM, and widely repeated planning ratios are rules of thumb rather than requirements. Actual demand depends on your working set, and the ARC is capped by default. Measure instead of assuming. Also note that ZFS on a single disk can detect bad blocks but has no second copy to repair from.
- LVM-thin is the lowest-overhead option: thin provisioning, snapshots, and no extra daemons. It has no checksum layer, no compression, and no built-in replication between nodes. Thin pool exhaustion is a genuine failure mode — if the pool fills, writes fail and guests can go down.
- Ceph RBD scales out and self-heals, and lets guests migrate between nodes without shared-storage tricks. It also needs a cluster: typically at least three nodes for monitor quorum and for replica placement to mean anything. A single-node Ceph install is a lab exercise, not a redundancy plan, and RBD mirroring is not enabled just by adding the storage to Proxmox.
Concrete implementation: a mirrored ZFS pool as VM storage
This path gives you snapshots, cloning, and checksums on a single node with two spare disks. It assumes the disks are empty and that you are not reusing an existing pool.
Do not name the pool rpool. If the node was installed with ZFS as its root filesystem, the installer already created a pool named rpool, and reusing that name collides with it. Use something else, such as tank.
- Identify the target disks and confirm they hold nothing you need:
lsblk -o NAME,SIZE,MODEL,TYPE wipefs -n /dev/sdb /dev/sdcwipefs -nis a dry run: it lists existing signatures without removing them.zpool createwill overwrite them, so check first. - Create the mirrored pool:
zpool create -o ashift=12 tank mirror /dev/sdb /dev/sdcashift=12requests a 4 KiB sector size, which suits many modern SSDs and HDDs. Confirm the appropriate value for your specific devices before creating the pool. - Set compression on the pool's root dataset so newly created VM datasets inherit it:
The second command should reportzfs set compression=lz4 tank zfs get compression tanklz4with sourcelocal. - Add it to Proxmox as a ZFS storage, not a Directory storage. In the GUI: Datacenter → Storage → Add → ZFS. Set ID
tank, ZFS Pooltank, and Content to Disk image (add Container if you also want LXC on it). A Directory storage pointed at the pool mountpoint does not provide the ZFS snapshot and clone integration. The equivalent CLI form is:pvesm add zfspool tank --pool tank --content images,rootdir - Confirm Proxmox sees it:
Look forpvesm statustankwith statusactive. Note thatpveversion -vreports package versions, not storage state, so it is not the right check here.
Validation you can actually run
- Create a throwaway VM (for example VM 101) with its disk placed on
tank. - Take a snapshot:
qm snapshot 101 test-snap1 - Confirm it exists in both views:
You should see a dataset named likeqm listsnapshot 101 zfs list -t snapshot -r tanktank/vm-101-disk-0@test-snap1. - Clone from the snapshot:
The flag isqm clone 101 102 --name test-clone --snapname test-snap1 --storage tank--snapname; runqm clone --helpon your version to confirm the option name. - Start the clone and check the console. A clone that boots confirms the snapshot captured a usable disk.
- Check pool health:
zpool status tank— expectONLINEand no errors. - Run one backup and one restore against a different storage target, so the test proves the backup is independent of the pool:
Replacevzdump 101 --storage <backup-storage-id> --mode snapshot --compress zstd qmrestore /path/to/vzdump-qemu-101-*.vma.zst 103<backup-storage-id>with a storage ID that is nottank.--mode snapshotrequires snapshot-capable storage, which is one reason the ZFS plugin is worth using. Confirm the archive extension matches the compression you selected.
Limitations and checks before you commit
- ARC sizing. ZFS's ARC consumes memory. Commonly quoted ratios (a few GB per TB) are starting points, not requirements — real demand depends on your working set, and the ARC is capped by default. Measure on your own workload by reading
/proc/spl/kstat/zfs/arcstats, orarc_summaryif your ZFS userland package provides it. To cap it, setoptions zfs zfs_arc_max=<bytes>in/etc/modprobe.d/zfs.conf, then runupdate-initramfs -uand reboot. That changes system state, so record the previous value first. - Scrubs. Run
zpool scrub tankon a schedule and readzpool statusafterwards. On a mirror a scrub can repair bad blocks; on a single-disk pool it can only report them. - If you pick LVM-thin instead. Monitor the thin pool's data and metadata usage. A full thin pool causes writes to fail. There is no checksum layer to detect silent corruption, so pair it with backups you have restored at least once.
- Ceph prerequisites. A Ceph cluster needs multiple nodes for monitor quorum and for replica placement to provide real protection. Single-node Ceph has no fault tolerance. RBD mirroring to a second cluster is a separate feature with its own configuration and prerequisites.
- Version sensitivity. Storage plugin options, default compression algorithms, and replication support have changed across Proxmox VE releases. Treat these commands as a starting point and verify option names against your installed version before running them in production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.