Skip to content

Instantly share code, notes, and snippets.

@arcezd
Last active March 18, 2024 23:15
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arcezd/c8df7b8a5735c884b927b36c6cc73006 to your computer and use it in GitHub Desktop.
Save arcezd/c8df7b8a5735c884b927b36c6cc73006 to your computer and use it in GitHub Desktop.
Guide to move root Raspbian to LVM partition

Prepare the installation with LVM drivers

DISCLAIMER: Copied from [https://raspberrypi.stackexchange.com/questions/85958/easy-backups-and-snapshots-of-a-running-system-with-lvm/85959]

Moving the installation isn't the problem but the LVM drivers must be loaded on boot up so the root partition can be mounted and used for booting. Fortunately the Raspberry Pi supports loading a ramdisk for initrd so we have to do an additional step to create the initram containing drivers for LVM.

The following is only for a quick setup an initramfs where you have to monitor kernel updates by yourself. To use a more automated setup an initramfs you can look at How can I use an init ramdisk (initramfs) on boot up Raspberry Pi?.

If you are unexperienced with linux please try it first with a new image how I did for this How To. You can loose all data.

For reference I use Raspbian Buster with Desktop 2020-02-13, flashed it to a SD Card and boot it in a RasPi. First do an upgrade to get the latest software versions and install drivers:

rpi ~$ sudo -Es
rpi ~# apt update
rpi ~# apt full-upgrade
rpi ~# apt install initramfs-tools
rpi ~# apt install lvm2

I only use this installation on a RPi3 (incl. RPi3+) and a RPi4. Enable using an initramfs by settings in /boot/config.txt, but using the current kernel/module names. The current available kernel/module names you will find with, for example:

rpi ~# ls /lib/modules/
4.19.97+  4.19.97-v7+  4.19.97-v7l+  4.19.97-v8+

The following should be inserted at the top of /boot/config.txt. For further filter settings look at Conditional filters in config.txt.

[pi3]
initramfs initrd.img-4.19.97-v7+ followkernel
[pi4]
initramfs initrd.img-4.19.97-v7l+ followkernel
# if you want to use the experimental 64 bit kernel, then enable this instead
#arm_64bit=1
#initramfs initrd.img-4.19.97-v8+ followkernel
[all]

I only want to load listed modules into the ramdisk, not all possible. We have to set option list in /etc/initramfs-tools/initramfs.conf:

rpi ~# sed -i 's/^MODULES=most/MODULES=list/' /etc/initramfs-tools/initramfs.conf

If you have trouble with drivers of your hardware with this setting, for example for a display, then you can modify option MODULES for initramfs.

Now create the ramdisks. Because we create them on a fat filesystem (boot partition) you will get some warnings. fat does not support all options, but you can ignore the warnings.

rpi ~# mkinitramfs -o /boot/initrd.img-4.19.97-v7+ 4.19.97-v7+
rpi ~# mkinitramfs -o /boot/initrd.img-4.19.97-v7l+ 4.19.97-v7l+
rpi ~# apt clean

Reboot. It should do it as always but now using the initram. Check with:

rpi ~$ journalctl -b | grep initr
Apr 17 11:20:38 raspberrypi kernel: Trying to unpack rootfs image as initramfs...
Apr 17 11:20:38 raspberrypi kernel: Freeing initrd memory: 13448K

Moving Raspbian to the LVM volume

Poweroff your system and attach its SD Card to a debian like computer. It must also have LVM2 installed (sudo apt install lvm2) even you don't use it there. We need it to setup LVM on the SD Card. We will now backup the installation on the SD Card, create a logical volume (lv) there and restore it to the lv. I will create a volume of 6 GB. You can use what you like but leave enough space for snapshots. I suggest to start with minimal space because with LVM it is no problem to extend the volume at any time. My SD Card is attached to /dev/sdb:

Backup Raspbian

pc ~$ sudo -Es
pc ~# fsck.vfat /dev/sdb1
pc ~# fsck.ext4 -f /dev/sdb2
pc ~# mkdir /mnt/sdb2
pc ~# mount /dev/sdb2 /mnt/sdb2
pc ~# mount /dev/sdb1 /mnt/sdb2/boot
pc ~# tar -cvzf raspbian-buster.tar.gz -C /mnt/sdb2 -V "Backup of Raspbian Buster with Desktop" ./ # last characters are dot and slash
pc ~# umount /mnt/sdb2/boot /mnt/sdb2

If you like you can test the backup before overwriting the SD Card:

pc ~# tar -tvf raspbian-buster.tar.gz

Partition the SD Card, create LVM volumes and format them. You are free to use sizes what you like.

partition the SD Card

pc ~# parted /dev/sdb mktable msdos
pc ~# parted /dev/sdb mkpart primary fat32 2048s 257MiB
pc ~# parted /dev/sdb mkpart primary ext4 257MiB 100%
pc ~# parted /dev/sdb set 2 lvm on

Create volumes

pc ~# pvcreate /dev/sdb2         # define physical volume
pc ~# vgcreate rpi.vg /dev/sdb2  # create volume group using physical volume
pc ~# lvcreate rpi.vg --name root.lv --size 6GiB  # create logical volume in volume group

Format the volumes and mount them

pc ~# mkfs.vfat -F 32 -n BOOT /dev/sdb1
pc ~# mkfs.ext4 -L rootfs /dev/mapper/rpi.vg-root.lv
pc ~# mount /dev/mapper/rpi.vg-root.lv /mnt/sdb2
pc ~# mkdir /mnt/sdb2/boot
pc ~# mount /dev/sdb1 /mnt/sdb2/boot

Now we restore Raspbian into the new volumes:

pc ~# tar -xvf raspbian-buster.tar.gz -C /mnt/sdb2

Change device names in boot/cmdline.txt and in etc/fstab because they have changed. Set them to /dev/mmcblk0p1 and to /dev/mapper/rpi.vg-root.lv:

pc ~# sed -i 's/root=PARTUUID=[a-z0-9]*-02/root=\/dev\/mapper\/rpi.vg-root.lv/' /mnt/sdb2/boot/cmdline.txt
pc ~# sed -i 's/^PARTUUID=[a-z0-9]*-01/\/dev\/mmcblk0p1/' /mnt/sdb2/etc/fstab
pc ~# sed -i 's/^PARTUUID=[a-z0-9]*-02/\/dev\/mapper\/rpi.vg-root.lv/' /mnt/sdb2/etc/fstab

Clean up

pc ~# umount /mnt/sdb2/boot /mnt/sdb2
pc ~# fsck.vfat /dev/sdb1
pc ~# fsck.ext4 -f /dev/mapper/rpi.vg-root.lv
pc ~# rmdir /mnt/sdb2
pc ~# exit
pc ~$

Take snapshots and backups

Now put the SD Card into the raspi, boot and login. Everything should be the same as before but we can use the Logical Volume Manager. Look at man lvm what's available. You can make your first snapshot from this base installation so you can always revert to it:

rpi ~$ sudo lvcreate --snapshot --name rpi_base --size 6GiB rpi.vg/root.lv
rpi ~$ sudo lvs
LV       VG       Attr       LSize Pool Origin  Data%  Meta%  Move Log Cpy%Sync Convert
root.lv  rpi.vg   owi-aos--- 6.00g
rpi_base rpi.vg   swi-a-s--- 6.00g      root.lv 0.01
rpi ~$

Revert and remove(!) snapshot. You should create it afterwards immediately again.

rpi ~$ sudo lvconvert --merge rpi.vg/rpi_base
rpi ~$ sudo systemctl reboot

Be patient! It may take some time, about some minutes. Never switch off your raspi.

Login and immediately create the snapshot again:

rpi ~$ sudo lvcreate --snapshot --name rpi_base --size 6GiB rpi.vg/root.lv

To commit simply delete the snapshot:

rpi ~$ sudo lvremove rpi.vg/rpi_base

To make a backup: simply make a snapshot, mount it and backup it, e.g. with the base installation. You can use what ever backup tool you like.

rpi ~$ sudo mount /dev/mapper/rpi.vg-rpi_base /mnt/
rpi ~$ tar -czf - -C /mnt/ ./ | ssh backup-server dd of=raspi.tar.gz bs=10k

To boot into the snapshot: Modify /boot/cmdline.txt and /etc/fstab and change the entries:

/dev/mapper/rpi.vg-root.lv

to

/dev/mapper/rpi.vg-rpi_base

Then boot the RasPi. In case you have destroid your working system then you can revert it to the snapshot with:

rpi ~$ sudo lvconvert --merge rpi.vg/rpi_base

Before rebooting don't forget to change /boot/cmdline.txt back to root=/dev/mapper/rpi.vg-root.lv. Also revert the entry in /etc/fstab.

Don't forget

For future mounts of the SD Card on your PC don't forget to use:

pc ~$ sudo mount /dev/mapper/rpi.vg-root.lv /mnt/sdb2
pc ~$ sudo mount /dev/sdb1 /mnt/sdb2/boot

And don't forget to update the initramfs when you have made driver updates, for example:

rpi ~$ ls /lib/modules/
4.19.97+  4.19.97-v7+  4.19.97-v7l+  4.19.97-v8+
rpi ~$ sudo mkinitramfs -o /boot/initrd.img-4.19.97-v7+ 4.19.97-v7+
rpi ~$ sudo mkinitramfs -o /boot/initrd.img-4.19.97-v7l+ 4.19.97-v7l+

If the version changed then you must also update the entries in /boot/config.txt, otherwise the bootloader will not find the renamed kernel and boot stucks. Don't worry. You can attach the SD Card to your PC, mount it and correct config.txt.

references: [1] Can the raspberry boot to an LVM root partition? [2] Can a Raspberry Pi be used to create a backup of itself?

@NotBobTheBuilder
Copy link

Thank you so much for this guide - just used this today to move my raspberry pi from the SD card to an LVM configuration!

Great to have so much info on all these topics all in one place

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment