For development I like to take snapshots so I can easily revert to
original installation without flashing the SD Card again. For this we
have to setup LVM (Logical Volume Management) on the SD Card and move
the root partition to it. With LVM it is also very easy to make backups on the running system. For all this you have to make the following only one time. So I've made this answer to summarize all the
nice information on this page from today's view.
The problem is that we have to create an initramfs
with LVM drivers
so the raspi can boot and mount the root partition which is residing
on the logical volume. Creating the initramfs
must be done on an
operating system with ARM processor of course. I can't do this with my
PC, it's an intel one. So I must boot into the raspi with a temporary
installation only for creating the initramfs
. Afterwards we will remove
this installation and expand the volume group with its place so we have
the whole disk space for our working installation.
Prepare SD Card with LVM
Here I'll prepare a Raspian Lite image for example. Maybe you must have
to install the lvm management tools lvm2
.
Flash SD Card
pc ~$ sudo -Es
pc ~# dd if=Downloads/2017-11-29-raspbian-stretch-lite.img of=/dev/sdd bs=4M conv=fsync
Create additional LVM partition of 3 GB
pc ~# parted /dev/sdd print
[..]
Number Start End Size Type File system Flags
1 4194kB 47,7MB 43,5MB primary fat32 lba
2 48,2MB 1858MB 1810MB primary ext4
pc ~# parted /dev/sdd mkpart primary 1858MB 100%
pc ~# parted /dev/sdd set 3 lvm on
pc ~# pvcreate /dev/sdd3
pc ~# vgcreate rpi_vg /dev/sdd3
pc ~# lvcreate rpi_vg --name root_lv --size 3G
pc ~# mkfs.ext4 /dev/mapper/rpi_vg-root_lv
pc ~# e2label /dev/mapper/rpi_vg-root_lv rootfs
Mount the partitions and copy root partition to the LVM partition
pc ~# mkdir /mnt/{sdd1,sdd2,root_lv}
pc ~# mount /dev/sdd1 /mnt/sdd1
pc ~# mount /dev/sdd2 /mnt/sdd2
pc ~# mount /dev/mapper/rpi_vg-root_lv /mnt/root_lv
pc ~# rsync -ax /mnt/sdd2/ /mnt/root_lv/
Change device name in cmdline.txt
for root partition to /dev/mmcblk0p2
and in etc/fstab
to /dev/mmcblk0p1
and /dev/mmcblk0p2
because of this
Problem with device names for root partition.
Clean up
pc ~# umount /mnt/{sdd1,sdd2,root_lv}
pc ~# e2fsck -f /dev/sdd2
pc ~# e2fsck -f /dev/mapper/rpi_vg-root_lv
pc ~# rmdir /mnt/{sdd1,sdd2,root_lv}
pc ~# exit
pc ~$
Create initramfs with temporary installation
Boot the SD Card in a raspi.
After login to the raspberrypi first install lvm2
and reboot to take
affect. Be patient if it takes sometimes a little bit longer. There are
many mounts to unmount with timeout.
raspberrypi ~$ sudo apt install lvm2
raspberrypi ~$ sudo systemctl reboot
After login chroot into root_lv
and create the initramfs
with
mkinitramfs
.
pi@raspberrypi ~$ ls /dev/mapper/rpi_vg-root_lv
/dev/mapper/rpi_vg-root_lv
Give the kernels pseudo files to the chrooted system.
raspberrypi ~$ sudo -Es
raspberrypi ~# mount /dev/mapper/rpi_vg-root_lv /mnt/
raspberrypi ~# cd /mnt
raspberrypi ~# mount /dev/mmcblk0p1 boot/
raspberrypi ~# mount -t proc /proc proc
raspberrypi ~# mount -o bind /dev dev
raspberrypi ~# mount -o bind /dev/pts dev/pts
raspberrypi ~# mount -t sysfs /sys sys
raspberrypi ~# chroot /mnt/
Install `lvm2´ also in this system:
raspberrypi ~# apt install lvm2
Add this line to /boot/config.txt
without =
!:
initramfs initramfs.gz
Then correct device names for root partition like this:
raspberrypi ~# cat /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mapper/rpi_vg-root_lv rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
raspberrypi ~# cat /etc/fstab
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mapper/rpi_vg-root_lv / ext4 defaults,noatime 0 1
raspberrypi ~#
Now we are ready to create the initramfs
:
raspberrypi ~# mkinitramfs -o /boot/initramfs.gz
Reboot
raspberrypi ~# exit
raspberrypi ~# exit
raspberrypi ~$ sudo systemctl reboot
Work with the final installation
After login check if we are mounted on /dev/mapper/rpi_vg-root_lv
:
raspberrypi ~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
mmcblk0 179:0 0 7.5G 0 disk
├─mmcblk0p1 179:1 0 41.5M 0 part /boot
├─mmcblk0p2 179:2 0 1.7G 0 part
└─mmcblk0p3 179:3 0 5.8G 0 part
└─rpi_vg-root_lv 254:0 0 3G 0 lvm /
raspberrypi ~$
Now we can add the partition from the temporary installation to the volume
group, so we can use it to expand our logical volume for this system or
for snapshots.
raspberrypi ~$ sudo -Es
raspberrypi ~# pvcreate /dev/mmcblk0p2
raspberrypi ~# vgextend rpi_vg /dev/mmcblk0p2
raspberrypi ~# pvs
PV VG Fmt Attr PSize PFree
/dev/mmcblk0p2 rpi_vg lvm2 a-- 1.68g 1.68g
/dev/mmcblk0p3 rpi_vg lvm2 a-- 5.78g 2.78g
raspberrypi ~#
But if you have enough space on your SD Card it could be a good idea to leave the installation on /dev/mmcblk0p2 untouched. Sometimes after an update on the working installation on /dev/mmcblk0p3 I forgot to sudo mkinitramfs -o /boot/initramfs.gz
to also update the initramfs
, so boot fails. Rebooting into rescue partition on /dev/mmcblk0p2 and recreating initramfs
helps.
Update the installation.
raspberrypi ~# apt update
raspberrypi ~# apt full-upgrade
raspberrypi ~# mkinitramfs -o /boot/initramfs.gz
raspberrypi ~# apt clean
raspberrypi ~# exit
raspberrypi ~$ sudo systemctl reboot
Take snapshots and backups
Login. Now we should take our first snapshot from this base installation
so we can always revert to it:
raspberrypi ~$ sudo lvcreate --snapshot --name rpi_base --size 3G rpi_vg/root_lv
raspberrypi ~$ sudo lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root_lv rpi_vg owi-aos--- 3.00g
rpi_base rpi_vg swi-a-s--- 3.00g root_lv 0.00
raspberrypi ~$
Revert and remove(!) snapshot. You should create it afterwards immediately again.
raspberrypi ~$ sudo lvconvert --merge rpi_vg/rpi_base
raspberrypi ~$ sudo systemctl reboot
Be patient! It takes a long time. Never switch off your raspi.
Login
raspberrypi ~$ sudo lvcreate --snapshot --name rpi_base --size 3G rpi_vg/root_lv
To commit simply delete the snapshot:
raspberrypi ~$ 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
raspberrypi ~$ sudo mount /dev/mapper/rpi_vg-rpi_base /mnt/
raspberrypi ~$ tar -czf - -C /mnt/ ./ | ssh backup-server dd of=raspi.tar.gz bs=10k