Proxmox VEVI · ZFSZFS operations
ZFS snapshots, clones, and the snapshot lifecycle
What you'll learn
- Create, list, and destroy ZFS snapshots safely
- Use ZFS clones to spin up writable copies from snapshots
- Understand the snapshot retention model and how it interacts with backups
- Wire ZFS snapshots into PBS, zfs-auto-snapshot, and PVE backup jobs
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-07
ZFS snapshots, clones, and the snapshot lifecycle
ZFS snapshots are the cheapest, fastest snapshot system available on Proxmox. A snapshot is instantaneous regardless of dataset size, takes almost no space initially, and is the foundation for ZFS send / receive replication and PBS-style incremental backups. This lesson covers the operational patterns.
What a snapshot actually is
A ZFS snapshot is a bookmark on the dataset’s block tree at a point in time. It’s not a copy of the data — it’s a pointer that says “as of this moment, here’s where all the live blocks were.” Live blocks stay shared with the live dataset; new writes go to new blocks; old blocks stay reachable via the snapshot.
The storage cost is only the blocks that have changed since the snapshot. A 1 TB dataset with one snapshot taken yesterday and 1 GB of writes since uses 1 TB + 1 GB, not 2 TB.
Creating snapshots
# Snapshot a single dataset
zfs snapshot tank/vm-storage@daily-$(date +%Y-%m-%d)
# Recursive snapshot (the dataset and all children)
zfs snapshot -r tank/vm-storage@daily-$(date +%Y-%m-%d)
# Snapshot a single VM disk (PVE creates these as part of backup)
zfs snapshot tank/vm-storage/vm-100-disk-0@backup-2024-01-15
# Add a comment / property (useful for automation)
zfs snapshot tank/vm-storage@daily-2024-01-15 -o com.sun:auto-snapshot=true
Snapshots are visible in zfs list -t snapshot:
zfs list -t snapshot -o name,used,refer tank/vm-storage
NAME USED REFER
tank/vm-storage@daily-2024-01-13 1.2G 1.21T
tank/vm-storage@daily-2024-01-14 800M 1.22T
tank/vm-storage@daily-2024-01-15 1G 1.23T
The USED column is the snapshot’s exclusive space (blocks only
this snapshot references). The REFER column is what the snapshot
sees as the dataset’s used size at snapshot time.
Listing snapshots
# All snapshots on the system
zfs list -t snapshot -o name,creation
# Snapshots on a specific dataset (recursive)
zfs list -t snapshot -r tank/vm-storage -o name,creation,used
# Just the names
zfs list -H -t snapshot -o name tank/vm-storage
Snapshots appear in zfs list output but with @ in the name:
zfs list tank/vm-storage
NAME USED AVAIL REFER MOUNTPOINT
tank/vm-storage 10T 500G 10T /tank/vm-storage
tank/vm-storage@daily-2024-01-13 - - 1.21T -
tank/vm-storage@daily-2024-01-14 - - 1.22T -
tank/vm-storage@daily-2024-01-15 - - 1.23T -
Rolling back to a snapshot
DANGER: rolling back destroys all snapshots taken after the rollback target. ZFS protects you from accidental data loss this way.
# Roll back to the previous day
zfs rollback tank/vm-storage@daily-2024-01-14
# Force-rollback past intermediate snapshots (deletes the in-between)
zfs rollback -r tank/vm-storage@daily-2024-01-13
For VMs, don’t roll back the live disk snapshot while the VM is running. The rollback happens at the ZFS level; the running qemu process has no idea the disk changed, and you get filesystem corruption inside the guest. The safe pattern is:
- Stop the VM:
qm stop 100 - Roll back:
zfs rollback tank/vm-storage/vm-100-disk-0@yesterday - Start the VM:
qm start 100
If you really need to roll back a live disk, you can use qm rollback
which handles the orchestration for you — but it still stops the VM
briefly.
Clones — writable snapshots
A ZFS clone is a writable copy of a snapshot. It’s nearly free (no data copied at creation) and writes go to a new space. Clones are how you spin up a writable VM from a snapshot:
# Clone a snapshot to a new dataset
zfs clone tank/vm-storage/vm-100-disk-0@yesterday \
tank/vm-storage/vm-100-clone
# Promote the clone to a fully independent dataset
# (after this, deleting the original dataset no longer affects the clone)
zfs promote tank/vm-storage/vm-100-clone
PVE creates ZFS volumes for VMs as tank/vm-storage/vm-100-disk-0. A
PVE-managed snapshot is tank/vm-storage/vm-100-disk-0@backup-XXX.
A clone from that snapshot is a new ZFS volume with a different name,
which PVE can register as a new VM disk and attach to a new VM ID.
This is the foundation of “instant VM recovery from a snapshot”: clone the snapshot, attach to a new VM, start. Total time: seconds.
Snapshot retention
Snapshots accumulate. Without a retention policy, you’ll run out of pool capacity in weeks. Three patterns:
1. Manual pruning
# Delete snapshots older than 7 days
for snap in $(zfs list -H -t snapshot -o name -r tank/vm-storage | \
grep '@daily-' | head -n -7); do
zfs destroy "$snap"
done
# Or one at a time
zfs destroy tank/vm-storage@daily-2024-01-01
2. zfs-auto-snapshot
The zfs-auto-snapshot tool (Debian package zfs-auto-snapshot)
schedules hourly / daily / weekly / monthly snapshots with retention:
apt install -y zfs-auto-snapshot
# Enable daily snapshots with 30-day retention on tank/vm-storage
zfs set com.sun:auto-snapshot=true tank/vm-storage
zfs set com.sun:auto-snapshot:daily=true tank/vm-storage
zfs set com.sun:auto-snapshot:monthly=true tank/vm-storage
# Override retention globally
# (heredoc replaced)
echo "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> /etc/cron.d/zfs-auto-snapshot
echo "" >> /etc/cron.d/zfs-auto-snapshot
echo "# Keep 30 daily, 12 monthly, 0 weekly (daily is enough)" >> /etc/cron.d/zfs-auto-snapshot
echo "30 * * * * root /usr/local/sbin/zfs-auto-snapshot --quiet --syslog --label=daily --keep=30" >> /etc/cron.d/zfs-auto-snapshot
echo "0 0 1 * * root /usr/local/sbin/zfs-auto-snapshot --quiet --syslog --label=monthly --keep=12" >> /etc/cron.d/zfs-auto-snapshotsystemctl restart cron
3. PVE backup-driven snapshots
PVE’s vzdump creates a ZFS snapshot as part of the backup job,
keeps it during the backup, and destroys it after. This is the
right pattern for backup-driven retention — pvesm retention rules
control how many backup snapshots are kept.
# Set retention on the storage
pvesm set local-zfs --prune-backups keep-daily=7,keep-weekly=4,keep-monthly=12
ZFS snapshots and PBS
PBS can back up ZFS snapshots directly without walking the filesystem. This is the fastest backup mode for ZFS:
# PBS datastore on ZFS
pvesm add zfspool pbs-zfs --pool tank/pbs --content backup
# Each VM backup creates a ZFS snapshot on tank/vm-storage
# and sends the delta to PBS
The backup chain is:
- PVE creates
tank/vm-storage/vm-100-disk-0@vzdump-XXXZFS snapshot - PVE sends the snapshot’s data to PBS
- PVE destroys the ZFS snapshot (unless
--keep-when-no-backupis set, in which case it’s kept as a “local” backup)
For air-gapped or low-bandwidth environments, keep the local ZFS snapshot as a local backup:
# /etc/pve/vzdump.cron — add --keep-when-no-backup to keep local snapshots
vzdump 100 --storage local-zfs --mode snapshot --keep-when-no-backup --prune-backups keep-daily=7
Common mistakes
- Letting snapshots accumulate forever. A pool fills up, ZFS slows to a crawl, and you’ll restore from a corrupt or missing snapshot.
- Rolling back the live VM disk. Corrupts the guest filesystem. Stop the VM first.
- Confusing snapshots with backups. Snapshots are local. They protect against accidental deletion or rollback, not against host failure. Pair snapshots with PBS replication for off-host backup.
- Using
zfs destroy -rwithout thinking. The-rflag destroys the dataset and all its snapshots. Make sure you mean it.
Production considerations
- Snapshot cost grows with change rate. A dataset that sees 100 GB of writes per day needs 100 GB of snapshot capacity per day of retention. Plan capacity accordingly.
- Performance impact of frequent snapshots. Each snapshot is essentially free to create, but the space accounting during writes (which block belongs to which snapshot) adds overhead. Hourly snapshots on a busy pool can show measurable performance impact.
- Snapshotting a busy live VM — the snapshot is instantaneous because it’s a pointer, not a copy. The actual data copy happens lazily. Safe to do at any time.
- Cross-host ZFS send/receive is the fastest replication mode for ZFS. Incremental sends only the changed blocks.
Key takeaways
- Snapshots are pointers, not copies. Cheap to create, cheap to keep.
- Use zfs-auto-snapshot or PVE’s built-in retention to bound growth.
- Use
zfs cloneto spin up writable copies from snapshots. - Snapshots protect against accidental deletion, not host failure. Pair with PBS for off-host.
Knowledge check
Knowledge check · 4 questions
Q1. Why does ZFS rollback destroy snapshots taken AFTER the rollback target?
Q2. A ZFS clone consumes almost no space when it is created, however large the parent dataset is.
Q3. Which tool provides scheduled snapshot retention without writing your own cron job?
Q4. Which of these are appropriate snapshot retention policies? (Select all that apply)
Passing score: 75%. Answers are checked in this browser.