Moving Proxmox VM disks between storage pools
There are two situations that push you to move a Proxmox VE VM’s disks to a different storage pool. The first: you want to enable ZFS replication across cluster nodes, but the VM is sitting on LVM-thin storage, which doesn’t support it. The second: a pool fills up and something else on that pool is suffering for it. In both cases, qm move-disk handles the migration while the VM keeps running.
This is how the command works, how to run it safely, and two gotchas that showed up after I’d already moved the disks.
How qm move-disk works
Proxmox uses QEMU’s drive-mirror block job under the hood. While the VM runs, it continuously mirrors the disk to the target storage. When the mirror catches up to 100%, Proxmox pauses writes briefly and commits the final delta. The VM doesn’t shut down; there are a few seconds of I/O pause per disk at the end, not a full restart.
Before you start
Three things to check:
- Back up the VM first.
vzdump <vmid> --storage <backup-storage> --mode snapshot. The move is generally safe, but you want a recovery point. - Confirm the target pool has enough space.
zpool list <pool>. Available should exceed the disk size being moved. - Check for active backup jobs. If Proxmox Backup Server is running a job for the same VM, the move can conflict.
pvesh get /cluster/tasksshows what’s running.
Moving the disks
Start by listing the current disk layout:
qm config <vmid>
Note the disk identifiers (scsi0, efidisk0, etc.) and which storage pool they’re on. Then move one disk at a time:
qm move-disk <vmid> scsi0 pve-containers --delete 1
qm move-disk <vmid> efidisk0 pve-containers --delete 1
--delete 1 removes the source volume after a successful copy. If you’d rather be conservative, omit it on the first run and delete the orphaned volume manually once you’ve verified the VM is healthy.
Verify after all moves:
qm config <vmid> | grep -E 'scsi|virtio|efidisk'
qm status <vmid>
All disk references should show the target pool. The VM should still be running.
Rough timing (NVMe to SATA SSD):
- 32GB OS disk: ~10 minutes
- 8-9GB data disk: ~14 seconds (mostly thin-allocated)
- 128KB EFI disk: instant
Gotcha 1: the stale local-lvm definition
Once you’ve moved everything off local-lvm, the storage definition in Proxmox still exists. It’s cluster-wide config in /etc/pve/storage.cfg, so it applies to all nodes. If those nodes no longer have the underlying LVM thinpool, pvesm status will start reporting errors on every check:
no such logical volume pve/data
The fix is to verify nothing still references local-lvm, then remove the definition:
# Check no VM or CT configs still reference it
grep -r "local-lvm" /etc/pve/nodes/
# If nothing found, remove the storage
pvesm remove local-lvm
Run pvesm status again to confirm the errors are gone.
Gotcha 2: unused disk entries break replication
After a disk move, Proxmox sometimes leaves an unusedN entry in the VM’s config. These point at the old storage location - a dataset that no longer exists after you passed --delete 1. If you then set up ZFS replication, the job fails on the first run:
zfs error: cannot open 'pool/vm-<vmid>-disk-N': dataset does not exist
Proxmox tries to replicate every disk in the config, including unusedN entries. With a dangling reference, the replication job fails every cycle until you remove the entry. It won’t fix itself.
Find and clean up dangling entries before setting up replication:
# Check for unused entries
qm config <vmid> | grep unused
# Remove each one
qm set <vmid> --delete unused0
Replication setup
With the disks on ZFS, create a replication job through Datacenter → Replication → Add in the Proxmox UI, or via CLI:
pvesr create-local-job <vmid>-0 <target-node> --schedule '*/15'
The first run is a full sync. Subsequent runs are incremental. Fifteen-minute intervals work well for most homelab VMs.
What I would do differently
- Check for unused disk entries before setting up replication. Running
qm config <vmid> | grep unusedtakes two seconds and avoids a replication job that fails every fifteen minutes. - Remove the stale local-lvm definition the same day. Easy to defer and forget until monitoring starts alerting on it at 2am.
- Verify the VM between each disk move.
qm status <vmid>is quick and gives early warning if something went sideways mid-copy.
Related reading
Building a two-node Proxmox storage architecture with ZFS
Why I chose ZFS with local replication over shared storage for my Proxmox cluster, how I set it up, and what I learned about storage architecture in a two-node setup.
Consolidating audiobooks and ebooks into a single Audiobookshelf
I was running two media servers, Audiobookshelf for audiobooks and Kavita for ebooks, when one could do both. Rebuilding the homelab in v3 was the excuse to merge them: one Ansible-deployed Audiobookshelf, local-disk storage, and a USB-drive ZFS scare in the middle of the migration.
Fixing Proxmox replication when ZFS has no common base snapshot
A Pi-hole replica CT stopped replicating with "No common base snapshot on volume(s)." Here is how I traced it, cleared the broken snapshot chain, and rebuilt the replication job.
Ready to Transform Your Career?
Let's work together to unlock your potential and achieve your professional goals.