************************************ Raspberry Pi Backup and Restoration ************************************ .. include:: rpi_disclaimer.rst Backing up a functional Raspberry Pi can be problematic. Creating an image copy of a card works, but suffers from a number of frustrating limitations: #. The entire card, including any unused space, must be copied to disk. On a large capacity card, simply storing such a large image can be a problem. The image can be compressed, but can still be rather large. #. Writing the image from a backup requires a card of the same size or larger. #. Writing the image is slow, even with compressed images as the entire image, including empty space, must still be written to the card. This page summarizes some alternate methods that can be used to work around these problems. Copying card contents to disk ============================= Rather than copying a byte-by-byte image of a card, we can simply copy the contents of the card to disk. This eliminates the need to allocate space for, or re-write empty space, greatly speeding up the backup and restoration process. This procedure makes use of another Linux machine, or Raspberry Pi running booted from a different image to make a copy of the card to be backed up. This approach has the advantage of maintaining a current backup of the original card on disk. If the procedure is repeated periodically, filesystem changes will be written to disk using ``rsync`` to copy only changed files, greatly speeding up subsequent backups. Backup existing card -------------------- #. Insert the card to be backed up into a card reader and insert it into a running Raspberry Pi or other Linux system. Verify that the card is recognized as ``/dev/sda``:: cat /proc/partitions .. todo:: Verify 1st stage bootloader process. This isn't consistently documented. #. Create directories to hold ``boot`` and ``/`` (root) partitions:: mkdir boot mkdir root #. Create temporary mount points for the card partitions to be backed up:: mkdir /tmp/sda1 mkdir /tmp/sda2 #. Mount the existing ``boot`` and ``root`` partitions to the temporary mount points for reading:: mount /dev/sda1 /tmp/sda1 mount /dev/sda2 /tmp/sda2 #. Copy the existing ``boot`` and ``root`` partitions to the backup directories:: rsync -qaHAXS /tmp/sda1/ boot rsync -qaHAXS /tmp/sda2/ root .. todo:: Verify root permissions not needed for writing card contents with ``rsync``. #. Unmount the ``boot`` and ``root`` filesystems:: sudo umount /tmp/sda1 sudo umount /tmp/sda2 #. Remove the card reader with the original card and set the card aside for safekeeping. Write files to new card ----------------------- #. Insert the new card to be written to into a card reader and insert it into a running Raspberry Pi or other Linux system. Verify that the card is recognized as ``/dev/sda``:: cat /proc/partitions #. Partition the new card using ``fdisk``:: sudo fdisk /dev/sda #. Create a new 100 MB ``boot`` and `allocate the remaining space to the ``root`` partition:: o # clear the in memory partition table n # new boot partition p # primary partition 1 # partition number 1 0 # start at sector 0 +100M # 100 MB boot partition n # new root partition p # primary partition 2 # partition number 2 # default, start immediately after preceding partition # default, extend partition to end of disk a # make a partition bootable 1 # bootable partition is partition 1 -- /dev/sda1 p # print the in-memory partition table w # write the partition table q # and we're done .. todo:: investigate use of parted #. Format ``boot`` partition with vfat filesystem:: sudo mkfs.vfat /dev/sda1 #. Format ``root`` partition with ext4 filesystem:: sudo mkfs.ext4 /dev/sda2 #. Mount the newly-formatted partitions:: mount /dev/sda1 /tmp/sda1 mount /dev/sda2 /tmp/sda2 #. Copy the existing ``boot`` and ``root`` partitions to the backup directories using ``rsync``:: rsync -qaHAXS boot /tmp/sda1/ rsync -qaHAXS boot /tmp/sda2/ .. todo:: Verify root permissions not needed for writing card contents with ``rsync``. .. todo:: Verify directories are copied correctly. .. todo:: investigate --delete and --whole-file options for rsync #. Unmount the ``boot`` and ``root`` filesystems:: sudo umount /tmp/sda1 sudo umount /tmp/sda2 #. Remove the card reader with the duplicate card. Remove the card and boot it to verify everything is working properly. Direct card-to-card copy ======================== This approach is essentially the same as the card-to-disk copy, but eliminates the intermediate copying of files to intermediate disk storage. The original card contents are copied directly to a second card. This procedure also makes use of another Linux machine, or Raspberry Pi running booted from a different image to make a copy of the card to be backed up. .. caution:: This procedure writes disk content and files with your original card mounted. Pay careful attention to the source and destinations for file writes. In this procedure, the *original* card will be ``/dev/sdb`` and the *duplicate* card will be ``/dev/sda``. Prepare the duplicate card -------------------------- #. Insert the new card to be written to into a card reader and insert it into a running Raspberry Pi or other Linux system. Verify that the card is recognized as ``/dev/sda``:: cat /proc/partitions #. Partition the new card using ``fdisk``:: sudo fdisk /dev/sda #. Create the new ``boot`` and ``root`` partitions on the new card. This procedure will create a 100 MB ``boot`` partition and allocate the remaining space to the ``root`` partition:: o # clear the in memory partition table n # new partition p # primary partition 1 # partition number 1 # default - start at beginning of disk +100M # 100 MB boot partition n # new partition p # primary partition 2 # partition number 2 # default, start immediately after preceding partition # default, extend partition to end of disk a # make a partition bootable 1 # bootable partition is partition 1 -- /dev/sda1 p # print the in-memory partition table w # write the partition table q # and we're done #. Format ``boot`` partition with vfat filesystem:: sudo mkfs.vfat /dev/sda1 #. Format ``root`` partition with ext4 filesystem:: sudo mkfs.ext4 /dev/sda2 #. Mount the newly-formatted partitions:: mount /dev/sda1 /tmp/sda1 mount /dev/sda2 /tmp/sda2 Backup existing card -------------------- #. Insert the card to be backed up into a card reader and insert it into a running Raspberry Pi or other Linux system. Verify that the card is recognized as ``/dev/sdb``:: cat /proc/partitions #. Copy RPi boot image from existing card. The first 4M of a bootable image contains a boot image that must be present to boot the Raspberry Pi. Our first step is to create a copy of this 4M on disk:: dd if=/dev/sdb of=/dev/sda bs=512 count=8192 #. Create temporary mount points for the card partitions to be backed up:: mkdir /tmp/sdb1 mkdir /tmp/sdb2 #. Mount the existing ``boot`` and ``root`` partitions to the temporary mount points for reading:: mount /dev/sdb1 /tmp/sdb1 mount /dev/sdb2 /tmp/sdb2 #. Copy the existing ``boot`` and ``root`` partitions to the backup directories:: rsync -qaHAXS /tmp/sdb1/ /dev/sda1/ rsync -qaHAXS /tmp/sdb2/ /dev/sda2/ .. todo:: Verify root permissions not needed for writing card contents with ``rsync``. .. todo:: Verify directories are copied correctly. #. Unmount the original and backup filesystems:: sudo umount /tmp/sda1 sudo umount /tmp/sda2 sudo umount /tmp/sdb1 sudo umount /tmp/sdb2 #. Remove the card reader with the original card and set the card aside for safekeeping. #. Remove the card reader with the duplicate card. Remove the card and boot it to verify everything is working properly. In-place backup of running system to new card ============================================= .. todo:: Add fsfreeze instructions Enter single-user (recovery) mode --------------------------------- #. Reboot the Raspberry Pi to be backed up in single-user mode:: sudo init 1 Prepare the duplicate card -------------------------- #. Insert the new card to be written to into a card reader and insert it into a running Raspberry Pi or other Linux system. Verify that the card is recognized as ``/dev/sda``:: cat /proc/partitions #. Partition the new card using ``fdisk``:: sudo fdisk /dev/sda #. Create the new ``boot`` and ``root`` partitions on the new card. This procedure will create a 100 MB ``boot`` partition and allocate the remaining space to the ``root`` partition:: o # clear the in memory partition table n # new partition p # primary partition 1 # partition number 1 # default - start at beginning of disk +100M # 100 MB boot partition n # new partition p # primary partition 2 # partiton number 2 # default, start immediately after preceding partition # default, extend partition to end of disk a # make a partition bootable 1 # bootable partition is partition 1 -- /dev/sda1 p # print the in-memory partition table w # write the partition table q # and we're done .. todo:: Replace with: # Create partition table parted $DEST/ClusterHAT-$VER-lite-$REV-usbboot.img --script -- mklabel msdos parted $DEST/ClusterHAT-$VER-lite-$REV-usbboot.img --script -- mkpart primary fat32 0% 64M parted $DEST/ClusterHAT-$VER-lite-$REV-usbboot.img --script -- mkpart primary 64M 100% #. Format ``boot`` partition with vfat filesystem:: sudo mkfs.vfat /dev/sda1 #. Format ``root`` partition with ext4 filesystem:: sudo mkfs.ext4 /dev/sda2 #. Mount the newly-formatted partitions:: mount /dev/sda1 /tmp/sda1 mount /dev/sda2 /tmp/sda2 Backup existing card -------------------- #. Insert the card to be backed up into a card reader and insert it into a running Raspberry Pi or other Linux system. Verify that the card is recognized as ``/dev/mmcblk0``:: cat /proc/partitions #. Copy the existing ``boot`` and ``root`` partitions to the backup directories:: rsync -qaHAXS /boot/ /dev/sda1/ rsync -qaHAXS --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / /dev/sda2/ .. todo:: Verify root permissions not needed for writing card contents with ``rsync``. .. todo:: Verify directories are copied correctly. #. Create the system folders:: for NAME in /dev /proc /sys /tmp /run /mnt /media; do sudo mkdir /mnt/sda2/${NAME}; done #. Shut down the original system:: sudo shutdown -h now #. Remove the card reader with the duplicate card. Remove the duplicate card and swap it with the original card, then boot it to verify everything is working properly. Last edited on Aug 29, 2021. Last build on |today|. .. include:: rpi_footer.rst