Fri, 28 Oct 2011
Keywords: Virtualbox shrink disk size minimise
Update - 20.10.2020
Rather than messing about with single user mode the easiest way to run zerofree is by attaching the disks to another VM and running zerofree there.
Update - 19.07.2014
This is actually a little easier now. Or I know better, perhaps.
Again, there should be no snapshots.
1. On the VM install zerofree:
# aptitude install zerofree
2. Boot into single user mode.
3. Run zero free on each virtual disk:
# zerofree /dev/sda1 # zerofree /dev/sdb1
4. Power down the VM
(On a Windows guest, for steps 1-4 just download and run sdelete -z)
5. On Windows, compact each virtual disk:
> "c:\Program Files\Oracle\VirtualBox\VBoxManage" modifyhd root.vdi --compact
And you're done.
If you've been using VirtualBox for a while with dynamically allocated disks, you've probably found that the size of the virtual disk exceeds that of the data stored therein. Sometimes by quite some ammount. Once used, the disk space is never returned.
I recently bought an SSD and wanted to put one of my Ubuntu virtual machines on it, that being where I do most of my work. However, the three virtual disks being used by that VM had grown quite large - too large to store on my SSD. There were also snapshots in use, despite the VM apparently not using any. This, I suspect, may have been due to mounting a virtual disk from another VM which had snapshots. Or it might not. In any case, things were a little bit of a mess and I wanted to sort them out too.
The first thing I did was to clear out as much of the disks as I could that was just being used for storage. Then we get to the complicated part of trying to reduce their size. I have seen suggestions to use zerofree or resize2fs but it wasn't clear to me whether they worked with ext4. So here is the method I used.
1. Using VirtualBox 4.1.x, clone the VM. This removes all the problems with the snapshots and makes a single definitive copy of all the virtual disks. If you have more than one virtual disk, you could remove those disks beforehand, since copies of those disks are not actually required, though a copy of the disk containing the root filesystem is required.
2. Create new, empty virtual disks for each of your original disks.
3. Add these new empty disks to your VM, along with at least the copy of the root filesystem.
4. Start your VM, run fdisk and mkfs.ext4 or mkswap to create the filesystems.
5. Create mountpoints and mount your new and cloned disks.
6. For all filesystems except the root filesystem, run cp -a to populate the new disk either from the clone, if you made one, or just from wherever they are mounted on the VM.
7. For the root filesystem do the same, but this must be done from the clone.
8. Assume your new root filesystem is mounted as /mnt/root. Run:
# mount -o bind /proc /mnt/root/proc # mount -o bind /dev /mnt/root/dev # mount -o bind /dev/pts /mnt/root/dev/pts # mount -o bind /sys /mnt/root/sys
Edit /etc/fstab to reflect your new disk layout. If possible, it might be easier if you just mount the root filesytem at first and don't use the UUID format.
# chroot /mnt/root # grub-install --root-directory=/ /dev/hda
Replace hda with whichever device you are booting from.
# update-grub # exit
9. Create a new virtual machine, use your cloned one, or reuse your old one. Attach the appropriate disks and start the VM. If you are lucky, grub will be set up and the VM will boot.
10. Find out the UUIDs of your partitions by running blkid. Edit /etc/fstab appropriately and reboot.
11. Copy averything to where you want it to be. (My SSD.)
And that's all there is too it!