Repository navigation
An approach to a backup strategy
I use my Raspberry Pi 4 as a home file server but I also tinker with it a little.
Things can go wrong and to avoid losing access to my files for longer than necessary, I bought a spare SD card and a USB adapter. The SD card is a clone from a backup of my main internal primary SD card.
First, I installed raspbian on the primary 32 GB SD card. In this instance, I used the Raspberry Pi Imager. Your own ways will be just as good. The reason I chose the RPImager was to have a minimalist boot SD (i.e. /boot and / partitions only).
The next step was to create a means of cloning the primary 32 GB SD card.
There is a plethora of tools and approaches, all with their own use-case, together with their own pros and cons.
I wanted a solution that offers these features:
- transportable backup for peace of mind, sharing, etc.
- performed entirely from the RPi4, remotely, without having to pop the SD cards, use another computer etc.
- faithfully clones the filesystem contents including all attributes
- space-efficient
- mountable image, to verify, browse or even restore files individually
- restorable to any appropriate device - in particular my primary and spare SD cards are not the same brand and have different geometry
I do not require differential or incremental backups, after all this is a full OS partition clone.
After an initial trial with dump/restore, I settled for e2image (my root partition is ext4 formatted). It produces a 1.7 GB file from the 30 GB root partition which compresses down to under 900MB with LZO (for speed over compression).
On a high level, back-up steps are:
# create backup:
e2image -ra -f "${TARGET}" "${IMAGE_FULL_FILENAME}"
# check and repair filesystem (resize2fs requires it):
e2fsck -f -E fixes_only -t -t -v -y "${IMAGE_FULL_FILENAME}"
# additional maintenance to slightly improve filesystem shrink result:
e2fsck -f -D -E discard,optimize_extents,bmap2extent -t -t -v -y "${IMAGE_FULL_FILENAME}"
e4defrag "${IMAGE_FULL_FILENAME}"
# shrink the backup's filesystem to minimise its size as much as possible
resize2fs "${IMAGE_FULL_FILENAME}" -pM
# compress the image, lzo is very fast to compress and decompress the image
# albeit compression is not as good as other compressors, it is massively faster
# and it still shaves off almost 50% of the size of the backup file.
lzop --delete "${IMAGE_FULL_FILENAME}"For illustration, I'm using a loopback device where I'll be restoring the backup (in place of my spare SD card):
# create regular file (~ 4 GB):
dd if=/dev/zero of=file_test_device.img bs=1024k count=4000
# associate the file-based test device to a loop device
losetup --find --show file_test_device.img
# create a dos partition table and one single partition that takes the entire available space (i.e. ~ 4 GB):
parted file_e2fs.img mklabel msdos
parted file_e2fs.img --align=optimal mkpart primary ext4 2048s "100%"
# inform the kernel of the changes to the file-based test loop device:
partprobe
# or assuming /dev/loop0:
losetup --detach /dev/loop0 && losetup --find --show --partscan file_test_device.imgTo restore a backup:
# decompress the backup:
lzop --keep -d "${IMAGE_FULL_FILENAME}".lzo
# for the purpose of this example, assuming /dev/loop0 with partition 1 on /dev/loop0p1
# restore the backup (note that the destination partition must be large enough or `e2image` will fail:
e2image -ra "${IMAGE_FULL_FILENAME}" /dev/loop0p1
# resize the file-system to match the partition's geometry:
# note: the partition's size (in sectors) can be found with `cat /sys/block/loop0/loop0p1/size`
# omitting the size parameter will default to the size of the partition:
resize2fs /dev/loop0p1 -p
rm "${IMAGE_FULL_FILENAME}" # the .lzo file should still exist