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.
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
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
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?
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