Anyone who runs critical services such as web servers or private clouds on a Raspberry Pi is well advised to produce regular backups. The usual procedure is to remove the SD card, put it into your notebook and produce a card image with dd
. This approach is as popular as it is inefficient: removing the SD card means that the system has to shut down completely. It is therefore impossible to run these backups unattended at regular intervals. Furthermore, dd
also backs up empty spaces on the SD card, i.e. time and disk space are wasted. The raspiBackup script promises to be a more intelligent solution, allowing “hot backups” onto local and remote devices while the system is running.
1. Remote backup destination should be NFS
Although raspiBackup allows for mounting local media, we would prefer to perform the backup of our Pi over the network. Keep in mind, that our Pi ZeroW does not even come with a grown up USB port to attach a memory stick to.
The protocol used for sharing data over the network should satisfy the following basic requirements:
- it should allow symlinks and so called “hard links” in order to work efficiently with rsync which acts inside of raspiBackup
- it should follow the logic of chmod and chown permissions for files and directories on Linux systems
Besides being complicated to set up on the file server, the popular samba protocol fails these requirements. The same goes for the handy sshfs protocol. Neither of these protocols can handle hard links. We therefore go for the NFS protocol which should suffice our requirements.
1.1 Prepare NFS directory on the destination machine
There is a very good description on sharing files over the NFS system on howtoforge.com. Make sure that the nfs-kernel-server
package is installed on the destination machine.
We first create the directory which is to be shared. We deviate from the instruction to create such a directory under /var/nfs
because we do not want to have write-intensive operations on the SSD and our /var
partition on the server would have insufficient disk space to hold large amounts of backup data from the Raspberry.
1 2 |
sudo mkdir /home/nfs sudo chown nobody:nogroup /home/nfs |
Next we will have to edit /etc/exports
. As the raspiBackup script will perform chown
operations in the destination folder, the NFS access must be granted in a way that super user operations can be performed. This is done by the switch no_root_squash
in the config file.
1 |
/home/nfs zerow(rw,sync,no_root_squash,no_subtree_check) |
Note that each client to which the file system needs a line. So if you have another client with host name pi3bp, you have to add another entry to /etc/exports
. Also note, that you can only use the host name if you have associated it to an ip-address in /etc/hosts
. If this is not the case, you have to use the ip-address, e.g.:
1 |
/home/nfs 192.168.4.63(rw,sync,no_root_squash,no_subtree_check) |
We refresh the current NFS configuration and start the NFS service:
1 2 |
sudo exportfs -a sudo service nfs-kernel-server start |
1.2 Prepare the Raspberry client to access the NFS drive
Make sure you have the nfs-common
package on your Raspberry.
Next we need a point in the Raspberry directory structure to mount the remote NFS on. We therefore create a directory:
1 |
pi@zerow:/srv $ sudo mkdir -p /mnt/nfs/backups |
As we want to access this directory through raspiBackup with super user privileges, there is no need to alter ownership, group membership and access privileges.
Mount the remote file system to that directory on the raspberry by:
1 |
pi@zerow:/srv $ sudo mount 192.168.4.41:/home/nfs /mnt/nfs/backups/ |
We are now connected to the remote file system on the server which stores the backup.
2. Download, Installation and Configuration of raspiBackup
I tried my luck with the raspiBackup script. Download links and installation instructions can be found at the raspiBackup home page.
2.1 Initial Setup
After downloading the raspiBackup configuration and programm code resides under /usr/local/bin
. For configuration and updates, call
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
pi@zerow:/usr/local/bin $ sudo raspiBackupInstall.sh --- RBI0001I: raspiBackupInstall.sh 0.3.7, 2018-07-14/17:59:44 - 5f9e49b --- RBI0055I: Using logfile raspiBackupInstall.log. --- RBI0057I: Checking internet connection. --- RBI0032I: Checking if there is a beta version available. --- RBI0014I: Downloading https://www.linux-tips-and-tricks.de/downloads/raspibackup0613-properties/download... --- RBI0053I: Installing raspiBackup.sh 0.6.4.2. --- RBI0041I: Default option is in UPPERCASE. --- RBI0002I: Message language (de|EN) : --- RBI0003I: Normal or partition oriented mode (N|p) : --- RBI0004I: Backuptype (dd|tar|RSYNC) : --- RBI0006I: Number of backups (1-52) : 3 --- RBI0008I: Verbose messages (Y|n) : --- RBI0042I: Selected configuration: Message language: en, Backupmode: normal, Backuptype: rsync --- RBI0048I: Selected configuration: Compress backups: n, Number of backups: 3, Verbose messages: y --- RBI0009I: Configuration OK (y|N) : y --- RBI0014I: Downloading raspiBackup.sh... --- RBI0037I: Created /usr/local/bin/raspiBackup.sh. --- RBI0037I: Created /usr/local/bin/raspiBackupInstall.sh. --- RBI0014I: Downloading raspiBackup.conf... --- RBI0037I: Created /usr/local/etc/raspiBackup.conf. --- RBI0024I: Updating configuration in /usr/local/etc/raspiBackup.conf. --- RBI0049I: Creating sample cron file /etc/cron.d/raspiBackup. --- RBI0023I: Installation of raspiBackup finished successfully. |
2.2 Amendments to raspiBackup.conf
Backup path
We still need to edit /usr/local/etc/raspiBackup.conf
and amend our mounted NFS directory as the destination:
1 |
DEFAULT_BACKUPPATH="/mnt/nfs/backups" |
Exclusion of directories
While raspiBackup excludes typical directories that are “not worth” being backed up (e.g. /tmp) automatically, it may make sense to exclude further directories.
A typical example is the local Nextcloud/ownCloud directory, which is already remotely stored on the Nextcloud server. As that server is also backed up, including the local /home/pi/ownCloud directory would mean duplicate backups.
These exclusions can be defined by the DEFAULT_EXCLUDE_LIST
parameter. Entries in that list must follow rsync conventions, i.e.
- each exclusion must be introduced by
--exclude=<relative path>
, - unlike when specifying source and destination paths the “trailing slash” has no effect. A directory in the exclude list will be excluded completely – with or without trailing slash.
- each directory must have a complete serparate exclude entry in the list. If you want to exclude dir1 and dir2, then the entrys must not be
--exclude=dir1 dir2
but--exclude=dir1 --exclude=dir2
The below is an example path which excludes the ownCloud directory and the directory holding the media for the minidlna server:
1 |
DEFAULT_EXCLUDE_LIST="--exclude /home/pi/owncloud/ --exclude var/lib/minidlna/" |
SUSPENDING services DURING BACKUP
In order to prevent inconsistent data, it is advisable to stop services like mysqld, nginx, cron etc. After the backup is completed, each service must be restarted again. This is done by the DEFAULT_STOP_SERVICES
and DEFAULT_START_SERVICES
parameters.
Keep in mind that the order in which the services are started or stopped can make a difference. Below is an example of what the services entries might look like:
1 2 3 4 5 |
# commands to stop services before backup separated by && DEFAULT_STOPSERVICES="service cron stop && service nginx stop && service prosody stop && service minidlna stop && service mysql stop" # commands to start services after backup separated by && DEFAULT_STARTSERVICES="service mysql start && service minidlna start && service prosody start && service nginx start && service cron start" |
3. Performing Backups
Keep in mind that backups over the network can be extremely time consuming. The following table summarizes the time needed for backing up different Raspbian systems over NFS. “Initial backup” implies that each and every file on the source system has to be transferred over the network. After that backup is completed, another backup is relaunched (“resync”). As there have been no modifications to the system, it can be assumed that this is an (almost) pure check if each file on the source system has an identical counterpart on the backup system.
The time needed for a full sync can be interpreted as the “upper bound” of the backup time needed for a system of the given size while the “resync” time is a proxy for the lower bound.
[table id=20 /]
3.1 Manual start of the backup
Manual start of a backup is triggered by:
1 |
pi@pi3bp:/usr/local/bin $ sudo ./raspiBackup.sh -g |
4. Restore
Restore instructions are based on the procedures laid out on the raspiBackup page. We assume that the backup snapshots are on an NFS exported file system on a remote machine that we call the backup server.
Unlike the backup procedure, the restore procedure is not a “hot restore”, i.e. we have to remove the SD card from the Raspberry and put it into an Ubuntu machine that has raspiBackup installed and that we call the restore machine.
- Put the SD card tho which the backup shall be restored into a Ubuntu machine that has a SD card reader and raspiBackup installed.
- Export the backup directory on the remote server via NFS (see section 1.1, make sure your ubuntu restore client holding the SD card is listed in the
/etc/exports
entries on the backup server). - On the restore machine, mount the NFS directory
1sudo mount 192.168.4.41:/home/nfs /mnt/nfs/backups - On the restore machine, determine the path to the SD card. You can find that path by running
sudo parted -l
. In our case, it is/dev/mmcblk0
. - Once you know the default path, start the backup procedure, you need to be root:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
root@nordic:/usr/local/bin# sudo raspiBackup.sh -d /dev/mmcblk0 /mnt/nfs/backups/pi3test/pi3test-rsync-backup-20190419-181915/ --- RBK0009I: nordic: raspiBackup.sh V0.6.4.2 (74411c9) started at Mon Apr 22 15:20:29 CEST 2019. --- RBK0031I: Checking whether a new version of raspiBackup.sh is available. --- RBK0168I: :-D raspiBackup.sh beta version 0.6.4.3 is available. Any help to test this beta is appreciated. Just upgrade to the new beta version with option -U. Restore to the previous version with option -V --- RBK0114I: Visit https://www.linux-tips-and-tricks.de/en/versionhistory/ to read about the changes in the new version. !!! RBK0018W: Target /dev/mmcblk0 with 7.40 GiB is larger than backup source with 7.40 GiB. root partition will be expanded accordingly to use the whole space. !!! RBK0065W: Device /dev/mmcblk0 will be repartitioned and all data will be lost. --- RBK0067I: Current partitions on /dev/mmcblk0: Number Start End Size Type File system Flags 1 4.19MB 49.2MB 45.0MB primary fat32 lba 2 50.3MB 7948MB 7898MB primary ext4 !!! RBK0066W: Device /dev/mmcblk0 will be overwritten with the saved boot and root partition. --- RBK0038I: Are you sure? y/N y --- RBK0050I: Restoring backup from /mnt/nfs/backups/pi3test/pi3test-rsync-backup-20190419-181915. --- RBK0053I: Restoring first partition (boot partition) to /dev/mmcblk0p1. --- RBK0055I: Restoring second partition (root partition) to /dev/mmcblk0p2. --- RBK0033I: Please wait until cleanup has finished. --- RBK0076I: Restore finished successfully. --- RBK0010I: pi3test: raspiBackup.sh V0.6.4.2 (74411c9) stopped at Mon Apr 22 15:54:25 CEST 2019. |
As can be seen from the output, it takes about 1/2 hour to restore a 3 GB test system.
Unmount the SD card, put it into your Raspberry Pi and reboot the restored system.
5. Trouble shooting
I have had an issue with ACL (access control list) attributes for the /media/pi
directory. The raspiBackup FAQ recommends removing the acl
entry from the /etc/mke2fs.conf
file. It turns out this modification has not helped at all. Whether the acl
entry is removed on the Raspberry, on the server or on both systems – raspiSync will always abort the backup process saying it cannot handle ACL entries.
The solution was therefore to remove the ACL entry directly from the /media/pi
directory. ACL flagged directories can be recognized by the + in the ls -alh
output (e.g. drwxrwxr-x+
).