Compacting VM Disk Images

Dynamically-allocated virtual disks grow when the guest writes data but don’t shrink when the guest deletes it — the hypervisor can’t tell a deleted file’s blocks from live ones. Compaction reclaims that space: convince the guest to zero its free space, then ask the hypervisor to drop (or compress) the zeroed regions. Two preconditions hold across platforms: the disk must not be part of a snapshot chain, and it must not be encrypted — encrypted blocks are high-entropy and neither sparsify nor compress.

libvirt / qcow2

virt-sparsify (libguestfs) does the whole job — it zeroes free space inside the filesystems and writes a sparse output image, without needing guest cooperation:

virt-sparsify --compress /path/to/image.qcow2 /path/to/new-image.qcow2

It works on any disk image format libguestfs reads (--convert qcow2 changes format in the same pass) and cannot run in place — you need scratch space for the output file. Note the explicit exception: libguestfs can read encrypted disks but encrypted disks cannot be sparsified, which is the same precondition stated above.

VirtualBox (VDI)

VBoxManage only discards zeroed blocks, so the guest-side zeroing is on you.

Windows guest — prep thoroughly, then zero with Sysinternals SDelete:

  1. Disable the paging file (Settings → System → About → Advanced system settings → Performance → Advanced → Virtual memory) — pagefile blocks are un-zeroable churn
  2. Disk Cleanup on C: to remove temp files
  3. Defragment/consolidate free space: defrag C: /FreespaceConsolidate /Verbose
  4. Zero free space: sdelete -z C: (-z = zero free space; distinct from -c which cleans free space with the DoD overwrite pattern — for compaction you want zeros)

Then on the host:

vboxmanage modifymedium /path/to/image.vdi --compact

Remember to re-enable the paging file afterward.

Linux guest — same idea with dd:

sudo dd if=/dev/zero of=/temp.zeros bs=4096k   # runs until disk full
sudo rm -f /temp.zeros

then vboxmanage modifymedium --compact on the host.

Notes

  • --compact only works on VDI; for VMDK/VHD convert first.
  • On SSD-backed hosts with TRIM/discard enabled end-to-end (guest + controller + host), much of this happens continuously and manual compaction matters less.
  • Keep the zero-fill step in mind when the VM is a sensitive artifact (e.g. an engagement box you’re archiving): compaction is a storage operation, not sanitization — but SDelete’s -z pass does incidentally overwrite deleted guest data with zeros.
  • windows-services — the Windows guest prep (paging file, defrag) touches the same system knobs
  • icacls — checking permissions on image files when archiving lab VMs

Sources