Migrate a LXC's rootfs to BTRFS
Just how convenient would it be, if Proxmox containers would use a BTRFS subvolume as a rootfs? Snapshot, Backups, etc.–everything would be super easy.
But, installing Proxmox on a BTRFS disk is not enough, one has to use the command line to create a LXC container and specify BTRFS as the root filesystem1. Well, I learned about that, when ten containers were already up and running.
This post explores how to migrate the rootfs of an existing LXC container from a raw image (inside: ext4 filesystem) to a btrfs subvolume. It assumes that Proxmox is installed with the BTRFS disk option, so YMMV.
Step-by-step
If your container already exists, migration of its rootfs is actually easy and straightforward. In the following, replace XXX with the container ID.
- Shut down the LXC container.
- Find your current rootfs. In case it resides in
local-btrfsyou should find it under/var/lib/pve/local-btrfs/images/XXX/vm-XXX-disk-0/disk.raw. This raw image file contains theext4root filesystem of your container.1
$ RAW_DISC_PATH=/var/lib/pve/local-btrfs/images/XXX/vm-XXX-disk-0/disk.raw
- Mount the root filesystem (this forum thread discusses how to do that in detail).
1 2 3
$ losetup --partscan /dev/loopXXX ${RAW_DISC_PATH} $ RAW_DISC_MNT=/var/lib/pve/local-btrfs/images/XXX/mnt-raw $ mount /dev/loopXXX ${RAW_DISC_MNT}
- Create the replacement btrfs filesystem.
1 2
$ BTRFS_SUBVOL=/var/lib/pve/local-btrfs/images/XXX/subvol-XXX-disk-0.subvol $ btrfs subvol create ${BTRFS_SUBVOL}
- Copy the file contents from the mounted raw disk to the BTRFS subvolume, and then unmount the raw disk.
1 2
$ rsync -avz ${RAW_DISC_MNT}/* ${BTRFS_SUBVOL}/ $ umount ${RAW_DISC_MNT}
- Update the config
/etc/pve/lxc/XXX.conf.1 2
-rootfs: local-btrfs:XXX/vm-XXX-disk-0.raw,size=6G +rootfs: local-btrfs:XXX/subvol-XXX-disk-0.subvol,size=6G
- Start up your container and clean up the old root disk.
And everything should just work :)
Caveats
There is one thing to consider, though: if a container is required to create subvolumes, it needs to be a priviledged container. This can be problematic in case you want an unpriviledged container to run docker or podman.