rsync-system-backup: Linux system backups powered by rsync¶
Welcome to the documentation of rsync-system-backup version 1.1!
User documentation¶
The readme explains the high level concepts and is mostly targeted at users of the command line interface. It’s probably the best place to start reading:
rsync-system-backup: Linux system backups powered by rsync¶
The rsync-system-backup program uses rsync to create full system backups of Linux systems. Supported backup destinations include local disks (possibly encrypted using LUKS) and remote systems that are running an SSH server or rsync daemon. Each backup produces a timestamped snapshot and these snapshots are rotated according to a rotation scheme that you can configure. The package is currently tested on cPython 2.7, 3.4, 3.5, 3.6, 3.7 and PyPy (2.7).
Status¶
While this project brings together more than ten years of experience in creating (system) backups using rsync, all of the actual Python code was written in the first few months of 2017 and has seen limited real world use. The project does however have an automated test suite with more than 90% test coverage and my intention is to extend the test coverage further.
In May 2018 I changed the status from alpha to beta as part of release 1.0. The bump in major version number was triggered by a backwards incompatible code change, however at that point I had been using rsync-system-backup to make local backups of several of my Linux systems for the majority of a year. Also several colleagues of mine have used the how-to on setting up unattended backups to an encrypted USB disk.
Warning
Please use the --dry-run
option when you’re getting familiar
with how rsync-system-backup works and don’t remove the option
until you’re confident that you have the right command line,
because using rsync-system-backup in the wrong way can cause
data loss (for example by accidentally swapping the SOURCE
and DESTINATION
arguments).
Installation¶
The rsync-system-backup package is available on PyPI which means installation should be as simple as:
$ pip install rsync-system-backup
There’s actually a multitude of ways to install Python packages (e.g. the per user site-packages directory, virtual environments or just installing system wide) and I have no intention of getting into that discussion here, so if this intimidates you then read up on your options before returning to these instructions ;-).
Usage¶
There are two ways to use the rsync-system-backup package: As the command
line program rsync-system-backup
and as a Python API. For details about the
Python API please refer to the API documentation available on Read the Docs.
The command line interface is described below.
Command line¶
Usage: rsync-system-backup [OPTIONS] [SOURCE] DESTINATION
Use rsync to create full system backups.
The required DESTINATION argument specifies the (possibly remote) location where the backup is stored, in the syntax of rsync’s command line interface. The optional SOURCE argument defaults to ‘/’ which means the complete root filesystem will be included in the backup (other filesystems are excluded).
Please use the --dry-run
option when getting familiar with this program and
don’t remove it until you’re confident that you have the right command line,
because using this program in the wrong way can cause data loss (for example
by accidentally swapping the SOURCE and DESTINATION arguments).
Supported locations include:
- Local disks (possibly encrypted using LUKS).
- Remote systems that allow SSH connections.
- Remote systems that are running an rsync daemon.
- Connections to rsync daemons tunneled over SSH.
The backup process consists of several steps:
- First rsync is used to transfer all (relevant) files to a destination directory (whether on the local system or a remote system). Every time a backup is made, this same destination directory is updated.
- After the files have been transferred a ‘snapshot’ of the destination
directory is taken and stored in a directory with a timestamp in its
name. These snapshots are created using ‘cp
--archive
--link
’. - Finally the existing snapshots are rotated to purge old backups according to a rotation scheme that you can customize.
Supported options:
Option | Description |
---|---|
-b , --backup |
Create a backup using rsync but don’t create a snapshot and don’t rotate
old snapshots unless the --snapshot and/or --rotate options are also given. |
-s , --snapshot |
Create a snapshot of the destination directory but don’t create a backup
and don’t rotate old snapshots unless the This option can be used to create snapshots of an rsync daemon module using
a ‘post-xfer exec’ command. If DESTINATION isn’t given it defaults to the
value of the environment variable |
-r , --rotate |
Rotate old snapshots but don’t create a backup and snapshot unless the
This option can be used to rotate old snapshots of an rsync daemon module
using a ‘post-xfer exec’ command. If DESTINATION isn’t given it defaults to
the value of the environment variable |
-m , --mount=DIRECTORY |
Automatically mount the filesystem to which backups are written. When this option is given and An entry for the mount point needs to be defined in /etc/fstab for this to work. |
-c , --crypto=NAME |
Automatically unlock the encrypted filesystem to which backups are written. When this option is given and the An entry for the encrypted filesystem needs to be defined in /etc/crypttab for this to work. If the device of the encrypted filesystem is missing and rsync-system-backup is being run non-interactively, it will exit gracefully and not show any desktop notifications. If you want the backup process to run fully unattended you can configure a key file in /etc/crypttab, otherwise you will be asked for the password each time the encrypted filesystem is unlocked. |
-t , --tunnel=TUNNEL_SPEC |
Connect to an rsync daemon through an SSH tunnel. This provides encryption
for rsync client to daemon connections that are not otherwise encrypted.
The value of TUNNEL_SPEC is expected to be an SSH alias, host name or IP
address. Optionally a username can be prefixed (followed by ‘@’) and/or a
port number can be suffixed (preceded by ‘:’). |
-i , --ionice=CLASS |
Use the ‘ionice’ program to set the I/O scheduling class and priority of
the ‘rm’ invocations used to remove backups. CLASS is expected to be one of
the values ‘idle’, ‘best-effort’ or ‘realtime’. Refer to the man page of
the ‘ionice’ program for details about these values. |
-u , --no-sudo |
By default backup and snapshot creation is performed with superuser
privileges, to ensure that all files are readable and filesystem
metadata is preserved. The -u , --no-sudo option disables
the use of ‘sudo’ during these operations. |
-n , --dry-run |
Don’t make any changes, just report what would be done. This doesn’t
create a backup or snapshot but it does run rsync with the --dry-run
option. |
--multi-fs |
Allow rsync to cross filesystem boundaries. This option has the opposite
effect of the rsync option --one-file-system because rsync-system-backup
defaults to running rsync with --one-file-system and must be instructed
not to using --multi-fs . |
-x , --exclude=PATTERN |
Selectively exclude certain files from being included in the backup.
Refer to the rsync documentation for allowed PATTERN syntax. Note that
rsync-system-backup always uses the ‘rsync --one-file-system ’ option. |
-f , --force |
By default rsync-system-backup refuses to run on non-Linux systems because
it was designed specifically for use on Linux. The use of the -f , --force
option sidesteps this sanity check. Please note that you are on your own if
things break! |
--disable-notifications |
By default a desktop notification is shown (using notify-send) before the system backup starts and after the backup finishes. The use of this option disables the notifications (notify-send will not be called at all). |
-v , --verbose |
Make more noise (increase logging verbosity). Can be repeated. |
-q , --quiet |
Make less noise (decrease logging verbosity). Can be repeated. |
-h , --help |
Show this message and exit. |
How it works¶
I’ve been finetuning my approach to Linux system backups for years now and during that time rsync has become my swiss army knife of choice :-). I also believe that comprehensive documentation can be half the value of an open source project. The following sections attempt to provide a high level overview of my system backup strategy:
The (lack of) backup format¶
Each backup is a full copy of the filesystem tree, stored in the form of individual files and directories on the destination. This “backup format” makes it really easy to navigate through and recover from backups because you can use whatever method you are comfortable with, whether that is a file browser, terminal, Python script or even chroot :-).
Snapshots and hard links¶
Every time a backup is made the same destination directory is updated with
additions, updates and deletions since the last backup. After the backup is
done a snapshot of the destination directory is created using the command cp
--archive --link
with the current date and time encoded in the name.
Due to the use of hard links each “version” of a file is only stored once. Because rsync by default doesn’t modify files inplace it breaks hard links and thereby avoids modifying existing inodes. This ensures that the contents of snapshots don’t change when a new backup updates existing files. The combination of hard links and the avoidance of inplace modifications effectively provides a limited form of deduplication. Each snapshot requires a couple of megabytes to store the directory names and hard links but the contents of files aren’t duplicated.
The article Easy Automated Snapshot-Style Backups with Linux and Rsync contains more details about this technique.
Rotation of snapshots¶
Snapshots can be rotated according to a flexible rotation scheme, for example I’ve configured my laptop backup rotation to preserve the most recent 24 hourly backups, 30 daily backups and endless monthly backups.
Backup destinations¶
While developing, maintaining and evolving backup scripts for various Linux laptops and servers I’ve learned that backups for different systems require different backup destinations and connection methods:
Encrypted USB disks¶
There’s a LUKS encrypted USB disk on my desk at work that I use to keep hourly, daily and monthly backups of my work laptop. The disk is connected through the same USB hub that also connects my keyboard and mouse so I can’t really forget about it :-).
Before the backup starts, the encrypted disk is automatically unlocked and mounted. The use of a key file enables this process to run unattended in the background. Once the backup is done the disk will be unmounted and locked again, so that it can be unplugged at any time (as long as a backup isn’t running of course).
Local server (rsync daemon)¶
My personal laptop transfers hourly backups to the rsync daemon running on the server in my home network using a direct TCP connection without SSH. Most of the time the laptop has an USB Ethernet adapter connected but the backup runs fine over a wireless connection as well.
Remote server (rsync daemon over SSH tunnel)¶
My VPS (virtual private server) transfers nightly backups to the rsync daemon running on the server in my home network over an SSH tunnel in order to encrypt the traffic and restrict access. The SSH account is configured to allow tunneling but disallow command execution. This setup enables the rsync client and server to run with root privileges without allowing the client to run arbitrary commands on the server.
Alternative connection methods¶
Backing up to a local disk limits the effectiveness of backups but using SSH access between systems gives you more than you bargained for, because you’re allowing arbitrary command execution. The rsync daemon provides an alternative that does not allow arbitrary command execution. The following sections discuss this option in more detail.
Using rsync daemon¶
To be able to write files as root and preserve all filesystem metadata, rsync must be running with root privileges. However most of my backups are stored on remote systems and opening up remote root access over SSH just to transfer backups feels like a very blunt way to solve the problem :-).
Fortunately another solution is available: Configure an rsync daemon on the destination and instruct your rsync client to connect to the rsync daemon instead of connecting to the remote system over SSH. The rsync daemon configuration can restrict the access of the rsync client so that it can only write to the directory that contains the backup tree.
In this setup no SSH connections are used and the traffic between the rsync client and server is not encrypted. If this is a problem for you then continue reading the next section.
Enabling rsync daemon¶
On Debian and derivatives like Ubuntu you can enable and configure an rsync daemon quite easily:
Make sure that rsync is installed:
$ sudo apt-get install rsync
Enable the rsync daemon by editing
/etc/default/rsync
and changing the lineRSYNC_ENABLE=false
toRSYNC_ENABLE=true
. Here’s a one liner that accomplishes the task:$ sudo sed -i 's/RSYNC_ENABLE=false/RSYNC_ENABLE=true/' /etc/default/rsync
Create the configuration file
/etc/rsyncd.conf
and define at least one module. Here’s an example based on my rsync daemon configuration:# Global settings. max connections = 4 log file = /var/log/rsyncd.log # Defaults for modules. read only = no uid = 0 gid = 0 # Daily backups of my VPS. [vps_backups] path = /mnt/backups/vps/latest post-xfer exec = /usr/sbin/process-vps-backups # Hourly backups of my personal laptop. [laptop_backups] path = /mnt/backups/laptop/latest post-xfer exec = /usr/sbin/process-laptop-backups
The
post-xfer exec
directives configure the rsync daemon to create a snapshot once the backup is done and rotate old snapshots afterwards.Once you’ve created
/etc/rsyncd.conf
you can start the rsync daemon:$ sudo service rsync start
If you’re using a firewall you should make sure that the rsync daemon port is whitelisted to allow incoming connections. The rsync daemon port number defaults to 873. Here’s an iptables command to accomplish this:
$ sudo iptables -A INPUT -p tcp -m tcp --dport 873 -m comment --comment "rsync daemon" -j ACCEPT
Tunneling rsync daemon connections¶
When your backups are transferred over the public internet you should definitely use SSH to encrypt the traffic, but if you’re at all security conscious then you probably won’t like having to open up remote root access over SSH just to transfer backups :-).
The alternative is to use a non privileged SSH account to set up an SSH
tunnel that redirects network traffic to the rsync daemon. The login shell of
the SSH account can be set to /usr/sbin/nologin
(or something similar like
/bin/false
) to disable command execution, in this case you need to pass
-N
to the SSH client.
Contact¶
The latest version of rsync-system-backup is available on PyPI and GitHub. The documentation is hosted on Read the Docs and includes a changelog. For bug reports please create an issue on GitHub. If you have questions, suggestions, etc. feel free to send me an e-mail at peter@peterodding.com.
The following instructions are also intended for users of the command line interface but are too detailed to be included in the readme:
How to set up unattended backups to an encrypted USB disk¶
This document explains how to set up unattended Linux system backups to an encrypted USB disk using LUKS filesystem encryption. These instructions are tested on Ubuntu (to be more specific I’ve used this process on 12.04, 14.04 and 16.04) but I’d expect them to work just as well on Debian and Linux distributions based on Debian.
Most of the steps in this how-to should in fact work fine on any Linux system (maybe with minor adjustments here and there) however there is one important thing to note: the configuration file /etc/crypttab and the commands cryptdisks_start and cryptdisks_stop are a Debian-ism that may not be available on other Linux distributions. The relevant sections explain how to tackle this (long story short: I wrote a fallback).
Install rsync-system-backup¶
There are several ways to install rsync-system-backup, for example:
# Make sure pip (the Python package manager) and related packages are installed.
sudo apt-get install python-{pip,pkg-resources,setuptools}
# Use pip to install the Python package we need in /usr/local. The
# executable will be available at /usr/local/bin/rsync-system-backup.
sudo pip install --upgrade rsync-system-backup
You can can also install the Python package and its dependencies in your home directory if you prefer that over “polluting” the system wide /usr/local directory:
# Use pip to install the Python package we need in ~/.local. The
# executable will be available at ~/.local/bin/rsync-system-backup.
pip install --upgrade --user rsync-system-backup
If that is still “too global” for your tastes then feel free to set up a Python virtual environment ;-).
Prepare the disk encryption¶
Create a key file¶
We will use a key file to enable rsync-system-backup to unlock the encrypted USB disk without requiring user interaction due to a password prompt. Basically the contents of the key file will serve as an alternate password that can be used in a noninteractive setting.
# Create a directory to store the key file.
sudo mkdir -p /root/keys
# Generate the key file from two kilobytes of pseudorandom data.
sudo dd if=/dev/urandom of=/root/keys/backups.key bs=512 count=4
# Make sure the directory and key file are private to the root user.
sudo chown -R root:root /root/keys
sudo chmod u=rwx,go= /root/keys
sudo chmod u=r,go= /root/keys/backups.key
Warning
I’m assuming here that the computer that you want to create
backups of already has full disk encryption. If this is not the
case it means that anyone with physical access to the computer can
just power it off, rip out the hard disk and extract the contents
of /root/keys/backups.key
, compromising the security of your
backups!
Enable encryption on the USB disk¶
Enabling encryption on the USB disk will effectively wipe the existing contents of the disk, so you need to make sure of two things:
- The existing contents of the disk have been backed up.
- You’re specifying the correct device file in the following command (please triple check or you might wipe the wrong disk).
# Enable LUKS disk encryption on the USB disk.
sudo cryptsetup luksFormat /dev/sdx /root/keys/backups.key
In the command above /dev/sdx
is the device file (this is what you need to
change, see figuring out the correct device file for hints) and
/root/keys/backups.key
is the name of the key file that we created in the
previous step.
Careful readers will notice that I’m not bothering to create a partition table on the USB disk, that’s because we don’t need it :-).
Make sure the disk is not in use¶
The luksFormat
command above may give you an error like:
Cannot format device /dev/sdx which is still in use
If this happens then most likely the USB disk that you attached already has a filesystem on it and your desktop environment automatically mounted that filesystem. You will need to unmount that filesystem before you can enable encryption on the disk. If you don’t know how to do that:
Follow the steps in the section figuring out the correct device file and take note of the device file corresponding to the USB disk.
Run the
mount
command to get a list of mounted filesystems and look for lines that mention the relevant device file. Most likely a number will be appended at the end of the device file (this indicates a partition on the USB disk).For each of the relevant entries in the
mount
output, run the following command:sudo umount /dev/sdx1
In the command above
/dev/sdx1
is the device file of a partition on the USB disk (this is what you need to change).
Figuring out the correct device file¶
If you don’t know or you’re not sure what the device file for the
luksFormat
command above should be, here’s one relatively
foolproof way to figure it out:
Disconnect the USB disk from your computer.
Open a terminal and use the following command to observe new log entries being added to the system log:
# Follow the system log (watch for new entries). sudo tail -fn 0 /var/log/syslog
Connect the USB disk to your computer and give the disk a few seconds to spin up and properly establish a USB connection to your computer.
Observe the entries that just appeared in the system log. If you study them carefully you should be able to figure out the name of the device file.
Configure a recovery password¶
If your computer’s hard disk breaks or your computer is stolen you will lose the key file required to unlock your encrypted backups, which would be rather ironic but not in a fun way :-P. To avoid this situation we can configure the disk encryption with a recovery password:
# Configure a recovery password.
sudo cryptsetup --key-file=/root/keys/backups.key luksAddKey /dev/sdx
In the command above /dev/sdx
is the device file, this should be the same
device file you used in the previous step.
Configure the encrypted disk¶
Once encryption has been enabled we can configure the encrypted disk
in /etc/crypttab
. To do so we first need to determine the unique
identifier of the encrypted disk:
# Determine the UUID of the encrypted disk.
sudo blkid /dev/sdx
In the command above /dev/sdx
is the device file, this should be the same
device file you used in the previous step. The blkid
command will output a
string called a UUID (a universally unique identifier), you need to copy this
to your clipboard (or have photographic memory). Now that we know the UUID we
can add the /etc/crypttab
entry:
# Use a text editor to configure the encrypted disk.
sudo nano /etc/crypttab
If the file doesn’t exist yet it implies that you’re not using full disk encryption on your computer. Please reconsider! But I digress. Now you need to add a new line to the file, something like this:
backups UUID=13f6e17e-8c8b-4009-a7b3-356992415141 /root/keys/backups.key luks,discard,noauto
Replace the part after UUID=
with the output of blkid
. Everything else
should be fine as is, unless you’ve chosen a different location for the key
file.
Unlock the encrypted disk¶
Thanks to the /etc/crypttab
entry that we added in the previous step,
unlocking the disk is very simple:
# Unlock the encrypted backups disk.
sudo cryptdisks_start backups
This won’t ask for a password because we configured a key file. If you get a “command not found” error then here are two suggestions:
If you’re running a Linux distribution based on Debian (like Ubuntu) then you can install cryptdisks_start and cryptdisks_stop as follows:
# Make sure `cryptdisks_start' and `cryptdisks_stop' are installed. sudo apt-get install cryptsetup
If you’re running a Linux distribution that’s not based on Debian then the cryptdisks_start and cryptdisks_stop programs may not be available to you. Don’t worry though, I’ve got your back! ;-)
Because we’ve already installed rsync-system-backup its dependencies are also available. One of these dependencies installs the following two command line programs:
cryptdisks-start-fallback
cryptdisks-stop-fallback
These programs are not as full featured as their “official” counterparts but they should work fine for the purposes of this how-to. Instead of the command given at the start of this section, please use the following command:
sudo cryptdisks-start-fallback backups
Prepare the encrypted filesystem¶
Format the encrypted filesystem¶
After the encrypted disk is unlocked using cryptdisks_start
the device file
/dev/mapper/backups
provides access to the unlocked data. Encrypting the
disk hasn’t created an actual filesystem yet so that’s what we’ll do next:
sudo mkfs.ext4 /dev/mapper/backups
Configure the encrypted filesystem¶
We’ll add an entry to /etc/fstab
so that it’s as easy to mount the
filesystem as it was easy to unlock the disk:
# Use a text editor to configure the encrypted filesystem.
sudo nano /etc/fstab
Add a new line to the file, something like this:
/dev/mapper/backups /mnt/backups ext4 noauto,errors=remount-ro 0 0
Also make sure the mount point exists:
sudo mkdir -p /mnt/backups
Decide on a directory layout¶
On my backup disks I am using a directory layout of multiple levels because my backups and I go way back :-). The first level consists of the names I chose to describe the laptops I’ve had over the years:
- /mnt/backups
- zenbook
- hp-probook
- macbook-pro
Each of these directories has subdirectories with the names of the Ubuntu releases that were installed on those laptops over the years:
- /mnt/backups
- zenbook
- lucid
- precise
- hp-probook
- precise
- trusty
- macbook-pro
- xenial
- zenbook
Each of the directories named after an Ubuntu release stores a collection of timestamped system backups, something like this:
- /mnt/backups
- zenbook
- lucid
- 2011-02-05 15:30
- 2011-03-19 11:45
- precise
- 2013-04-10 14:00
- 2013-05-10 14:00
- lucid
- hp-probook
- precise
- 2014-03-12 16:15
- trusty
- 2016-06-15 12:00
- precise
- macbook-pro
- xenial
- 2017-03-19 23:15
- 2017-04-01 12:34
- 2017-05-02 17:00
- latest
- xenial
- zenbook
The dates were made up and in reality I have hundreds of timestamped system backups, but you get the idea :-).
Whether you use the same directory layout or something simpler is up to you.
Create your first backup¶
Here’s an example of how you can create a system backup:
sudo rsync-system-backup -c backups -m /mnt/backups /mnt/backups/latest
That last directory must be a subdirectory of /mnt/backups
, if you want to
keep things simple then just use /mnt/backups/latest
(whatever you do,
don’t just pass it /mnt/backups
).
If you get a “command not found” error from sudo
try the following instead:
sudo $(which rsync-system-backup) -c backups -m /mnt/backups /mnt/backups/latest
Configure unattended backups¶
The final part of this how-to configures your system to automatically run rsync-system-backup at an interval of your choosing, for example once every four hours. The easiest way to accomplish this is using cron. To do so we’ll create a new configuration file:
# Use a text editor to configure unattended backups.
sudo nano /etc/cron.d/rsync-system-backup
Create the file with the following contents:
# Cron by default starts subcommands in a very sparse environment where the
# $PATH contains just /usr/bin and /bin. Since we expect a reasonably sane
# $PATH we have to set it ourselves:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Create a full system backup every four hours.
0 */4 * * * root rsync-system-backup -c backups -m /mnt/backups /mnt/backups/latest
Depending on how you installed rsync-system-backup you may need to adjust the
PATH
variable or change the program name into an absolute pathname.
Silencing desktop notifications¶
When rsync-system-backup is running non-interactively and it finds that the device of the encrypted filesystem is missing, it will exit gracefully and not show any desktop notifications. This is intended to avoid noise when the backup disk isn’t connected.
If the desktop notifications announcing the start and completion of a system
backup drive you bonkers, add the --disable-notifications
option to the
rsync-system-backup command line to silence desktop notifications.
API documentation¶
The following documentation is targeted at people who are interested in using the Python API:
API documentation¶
The following documentation is based on the source code of version 1.1 of the rsync-system-backup package:
rsync_system_backup
¶
Simple to use Python API for Linux system backups powered by rsync.
The rsync_system_backup
module contains the Python API of the
rsync-system-backup package. The core logic of the package is contained in
the RsyncSystemBackup
class.
-
rsync_system_backup.
DEFAULT_ROTATION_SCHEME
= {'daily': 7, 'hourly': 24, 'monthly': 'always', 'weekly': 4}¶ The default rotation scheme for system backup snapshots (a dictionary).
-
class
rsync_system_backup.
RsyncSystemBackup
(**kw)[source]¶ Python API for the
rsync-system-backup
program.The
execute()
method is the main entry point. If you’re looking for finer grained control refer tounlock_device()
,mount_filesystem()
,transfer_changes()
,create_snapshot()
androtate_snapshots()
.When you initialize a
RsyncSystemBackup
object you are required to provide a value for thedestination
property. You can set the values of thebackup_enabled
,crypto_device
,destination
,dry_run
,exclude_list
,excluded_roots
,force
,ionice
,mount_point
,multi_fs
,notifications_enabled
,rotate_enabled
,rotation_scheme
,snapshot_enabled
,source
,source_context
andsudo_enabled
properties by passing keyword arguments to the class initializer.Here’s an overview of the
RsyncSystemBackup
class:-
backup_enabled
[source]¶ True
to enabletransfer_changes()
,False
otherwise.Note
The
backup_enabled
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
crypto_device
[source]¶ The name of the encrypted filesystem to use (a string or
None
).Note
The
crypto_device
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
crypto_device_available
¶ True
if the encrypted filesystem is available,False
otherwise.This property is an alias for the
is_available
property ofcrypttab_entry
.
-
crypto_device_unlocked
¶ True
if the encrypted filesystem is unlocked,False
otherwise.This property is an alias for the
is_unlocked
property ofcrypttab_entry
.
-
crypttab_entry
[source]¶ The entry in
/etc/crypttab
corresponding tocrypto_device
.The value of this property is computed automatically by parsing
/etc/crypttab
and looking for an entry whose target (the first of the four fields) matchescrypto_device
.When an entry is found an
EncryptedFileSystemEntry
object is constructed, otherwise the result isNone
.Note
The
crypttab_entry
property is acached_property
. This property’s value is computed once (the first time it is accessed) and the result is cached. To clear the cached value you can usedel
ordelattr()
.
-
destination
[source]¶ The destination where backups are stored (a
Destination
object).The value of
destination
defaults to the value of the environment variable$RSYNC_MODULE_PATH
which is set by the rsync daemon before it runs thepost-xfer exec
command.Note
The
destination
property is arequired_property
. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named destination (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.
-
destination_context
[source]¶ The execution context of the system that stores the backup (the destination).
This is an execution context created by
executor.contexts
.Raises: DestinationContextUnavailable
when the destination is an rsync daemon module (which doesn’t allow arbitrary command execution).Note
The
destination_context
property is acached_property
. This property’s value is computed once (the first time it is accessed) and the result is cached. To clear the cached value you can usedel
ordelattr()
.
-
dry_run
[source]¶ True
to simulate the backup without writing any files,False
otherwise.Note
The
dry_run
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
multi_fs
[source]¶ True
to allow rsync to cross filesystem boundaries,False
otherwise.This property has the opposite effect of the rsync command line option
--one-file-system
becausemulti_fs
defaults toFalse
which means rsync is run with--one-file-system
. You can setmulti_fs
toTrue
to omit--one-file-system
from the rsync command line.Note
The
multi_fs
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
exclude_list
[source]¶ A list of patterns (strings) that are excluded from the system backup.
The patterns in
exclude_list
are passed on to rsync using the--exclude
option.Note
The
exclude_list
property is acustom_property
. You can change the value of this property using normal attribute assignment syntax. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
excluded_roots
[source]¶ A list of patterns (strings) that are excluded from the system backup.
All of the patterns in this list will be rooted to the top of the filesystem hierarchy when they’re given the rsync, to avoid unintentionally excluding deeply nested directories that happen to match names in this list. This is done using the
--filter=-/ PATTERN
option.Note
The
excluded_roots
property is acustom_property
. You can change the value of this property using normal attribute assignment syntax. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
force
[source]¶ True
to run rsync-system-backup on unsupported platforms,False
otherwise.Note
The
force
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
ionice
[source]¶ The I/O scheduling class for rsync (a string or
None
).When this property is set ionice will be used to set the I/O scheduling class for rsync. This can be useful to reduce the impact of backups on the rest of the system.
The value of this property is expected to be one of the strings ‘idle’, ‘best-effort’ or ‘realtime’.
Note
The
ionice
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
mount_point
[source]¶ The pathname of the mount point to use (a string or
None
).Note
The
mount_point
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
mount_point_active
¶ True
ifmount_point
is mounted already,False
otherwise.
-
notifications_enabled
[source]¶ Whether desktop notifications are used (a boolean).
By default desktop notifications are enabled when a real backup is being made but disabled during dry runs.
Note
The
notifications_enabled
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
rotation_scheme
[source]¶ The rotation scheme for snapshots (a dictionary, defaults to
DEFAULT_ROTATION_SCHEME
).Note
The
rotation_scheme
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
snapshot_enabled
[source]¶ True
to enablecreate_snapshot()
,False
otherwise.Note
The
snapshot_enabled
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
source
[source]¶ The pathname of the directory to backup (a string, defaults to ‘/’).
Note
The
source
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
source_context
[source]¶ The execution context of the system that is being backed up (the source).
This is expected to be an execution context created by
executor.contexts
. It defaults toexecutor.contexts.LocalContext
.Note
The
source_context
property is acustom_property
. You can change the value of this property using normal attribute assignment syntax. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
rotate_enabled
[source]¶ True
to enablerotate_snapshots()
,False
otherwise.Note
The
rotate_enabled
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
sudo_enabled
[source]¶ True
to runrsync
and snapshot creation with superuser privileges,False
otherwise.Note
The
sudo_enabled
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
execute
()[source]¶ Execute the requested actions (backup, snapshot and/or rotate).
The
execute()
method defines the high level control flow of the backup / snapshot / rotation process according to the caller’s requested configuration:- When
backup_enabled
is setnotify_starting()
shows a desktop notification to give the user a heads up that a system backup is about to start (because the backup may have a noticeable impact on system performance). - When
crypto_device
is setunlock_device()
ensures that the configured encrypted device is unlocked. - When
mount_point
is setmount_filesystem()
ensures that the configured filesystem is mounted. - When
backup_enabled
is settransfer_changes()
creates or updates the system backup ondestination
using rsync. - When
snapshot_enabled
is setcreate_snapshot()
creates a snapshot of thedestination
directory. - When
rotate_enabled
is setrotate_snapshots()
rotates snapshots. - When
backup_enabled
is setnotify_finished()
shows a desktop notification to give the user a heads up that the system backup has finished (or failed).
- When
-
ensure_supported_platform
()[source]¶ Make sure we’re running on a supported platform.
Raises: UnsupportedPlatformError
when the output of theuname
command doesn’t include the word ‘Linux’ andforce
isFalse
.When
force
isTrue
this method logs a warning message instead of raising an exception.
-
unlock_device
()[source]¶ Automatically unlock the encrypted filesystem to which backups are written.
Raises: The following exceptions can be raised:
DestinationContextUnavailable
, refer todestination_context
for details.ExternalCommandFailed
when the cryptdisks_start command reports an error.
When
crypto_device
is set this method usescryptdisks_start()
to unlock the encrypted filesystem to which backups are written before the backup starts. Whencryptdisks_start()
was called before the backup started,cryptdisks_stop()
will be called when the backup finishes.To enable the use of
cryptdisks_start()
andcryptdisks_stop()
you need to create an /etc/crypttab entry that maps your physical device to a symbolic name. If you want this process to run fully unattended you can configure a key file in /etc/crypttab, otherwise you will be asked for the password when the encrypted filesystem is unlocked.
-
mount_filesystem
()[source]¶ Automatically mount the filesystem to which backups are written.
Raises: The following exceptions can be raised:
DestinationContextUnavailable
, refer todestination_context
for details.ExternalCommandFailed
when the mount command reports an error.
When
mount_point
is set this method uses the mount command to mount the filesystem to which backups are written before the backup starts. When mount was called before the backup started, umount will be called when the backup finishes. An entry for the mount point needs to be defined in /etc/fstab.
-
transfer_changes
()[source]¶ Use rsync to synchronize the files on the local system to the backup destination.
Raises: InvalidDestinationDirectory
whenmount_point
is set anddestination
is a local directory that is not located undermount_point
.
-
create_snapshot
()[source]¶ Create a snapshot of the destination directory.
Raises: The following exceptions can be raised:
DestinationContextUnavailable
, refer todestination_context
for details.ParentDirectoryUnavailable
, refer toparent_directory
for details.ExternalCommandFailed
when thecp
command reports an error.
-
rotate_snapshots
()[source]¶ Rotate system backup snapshots using
rotate_backups
.Raises: The following exceptions can be raised:
DestinationContextUnavailable
, refer todestination_context
for details.ParentDirectoryUnavailable
, refer toparent_directory
for details.- Any exceptions raised by
rotate_backups
.
The values of the
dry_run
,ionice
androtation_scheme
properties are passed on to theRotateBackups
class.
-
rsync_system_backup.cli
¶
Usage: rsync-system-backup [OPTIONS] [SOURCE] DESTINATION
Use rsync to create full system backups.
The required DESTINATION argument specifies the (possibly remote) location where the backup is stored, in the syntax of rsync’s command line interface. The optional SOURCE argument defaults to ‘/’ which means the complete root filesystem will be included in the backup (other filesystems are excluded).
Please use the --dry-run
option when getting familiar with this program and
don’t remove it until you’re confident that you have the right command line,
because using this program in the wrong way can cause data loss (for example
by accidentally swapping the SOURCE and DESTINATION arguments).
Supported locations include:
- Local disks (possibly encrypted using LUKS).
- Remote systems that allow SSH connections.
- Remote systems that are running an rsync daemon.
- Connections to rsync daemons tunneled over SSH.
The backup process consists of several steps:
- First rsync is used to transfer all (relevant) files to a destination directory (whether on the local system or a remote system). Every time a backup is made, this same destination directory is updated.
- After the files have been transferred a ‘snapshot’ of the destination
directory is taken and stored in a directory with a timestamp in its
name. These snapshots are created using ‘cp
--archive
--link
’. - Finally the existing snapshots are rotated to purge old backups according to a rotation scheme that you can customize.
Supported options:
Option | Description |
---|---|
-b , --backup |
Create a backup using rsync but don’t create a snapshot and don’t rotate
old snapshots unless the --snapshot and/or --rotate options are also given. |
-s , --snapshot |
Create a snapshot of the destination directory but don’t create a backup
and don’t rotate old snapshots unless the This option can be used to create snapshots of an rsync daemon module using
a ‘post-xfer exec’ command. If DESTINATION isn’t given it defaults to the
value of the environment variable |
-r , --rotate |
Rotate old snapshots but don’t create a backup and snapshot unless the
This option can be used to rotate old snapshots of an rsync daemon module
using a ‘post-xfer exec’ command. If DESTINATION isn’t given it defaults to
the value of the environment variable |
-m , --mount=DIRECTORY |
Automatically mount the filesystem to which backups are written. When this option is given and An entry for the mount point needs to be defined in /etc/fstab for this to work. |
-c , --crypto=NAME |
Automatically unlock the encrypted filesystem to which backups are written. When this option is given and the An entry for the encrypted filesystem needs to be defined in /etc/crypttab for this to work. If the device of the encrypted filesystem is missing and rsync-system-backup is being run non-interactively, it will exit gracefully and not show any desktop notifications. If you want the backup process to run fully unattended you can configure a key file in /etc/crypttab, otherwise you will be asked for the password each time the encrypted filesystem is unlocked. |
-t , --tunnel=TUNNEL_SPEC |
Connect to an rsync daemon through an SSH tunnel. This provides encryption
for rsync client to daemon connections that are not otherwise encrypted.
The value of TUNNEL_SPEC is expected to be an SSH alias, host name or IP
address. Optionally a username can be prefixed (followed by ‘@’) and/or a
port number can be suffixed (preceded by ‘:’). |
-i , --ionice=CLASS |
Use the ‘ionice’ program to set the I/O scheduling class and priority of
the ‘rm’ invocations used to remove backups. CLASS is expected to be one of
the values ‘idle’, ‘best-effort’ or ‘realtime’. Refer to the man page of
the ‘ionice’ program for details about these values. |
-u , --no-sudo |
By default backup and snapshot creation is performed with superuser
privileges, to ensure that all files are readable and filesystem
metadata is preserved. The -u , --no-sudo option disables
the use of ‘sudo’ during these operations. |
-n , --dry-run |
Don’t make any changes, just report what would be done. This doesn’t
create a backup or snapshot but it does run rsync with the --dry-run
option. |
--multi-fs |
Allow rsync to cross filesystem boundaries. This option has the opposite
effect of the rsync option --one-file-system because rsync-system-backup
defaults to running rsync with --one-file-system and must be instructed
not to using --multi-fs . |
-x , --exclude=PATTERN |
Selectively exclude certain files from being included in the backup.
Refer to the rsync documentation for allowed PATTERN syntax. Note that
rsync-system-backup always uses the ‘rsync --one-file-system ’ option. |
-f , --force |
By default rsync-system-backup refuses to run on non-Linux systems because
it was designed specifically for use on Linux. The use of the -f , --force
option sidesteps this sanity check. Please note that you are on your own if
things break! |
--disable-notifications |
By default a desktop notification is shown (using notify-send) before the system backup starts and after the backup finishes. The use of this option disables the notifications (notify-send will not be called at all). |
-v , --verbose |
Make more noise (increase logging verbosity). Can be repeated. |
-q , --quiet |
Make less noise (decrease logging verbosity). Can be repeated. |
-h , --help |
Show this message and exit. |
-
rsync_system_backup.cli.
enable_explicit_action
(options, explicit_action)[source]¶ Explicitly enable an action and disable other implicit actions.
Parameters: - options – A dictionary of options.
- explicit_action – The action to enable (one of the strings ‘backup_enabled’, ‘snapshot_enabled’, ‘rotate_enabled’).
rsync_system_backup.destinations
¶
Parsing of rsync destination syntax (and then some).
-
rsync_system_backup.destinations.
RSYNCD_PORT
= 873¶ The default port of the rsync daemon (an integer).
-
rsync_system_backup.destinations.
LOCAL_DESTINATION
= <_sre.SRE_Pattern object>¶ A compiled regular expression pattern to parse local destinations, used as a fall back because it matches any nonempty string.
-
rsync_system_backup.destinations.
SSH_DESTINATION
= <_sre.SRE_Pattern object>¶ A compiled regular expression pattern to parse remote destinations of the form
[USER@]HOST:DEST
(using an SSH connection).
-
rsync_system_backup.destinations.
SIMPLE_DAEMON_DESTINATION
= <_sre.SRE_Pattern object>¶ A compiled regular expression pattern to parse remote destinations of the form
[USER@]HOST::MODULE[/DIRECTORY]
(using an rsync daemon connection).
-
rsync_system_backup.destinations.
ADVANCED_DAEMON_DESTINATION
= <_sre.SRE_Pattern object>¶ A compiled regular expression pattern to parse remote destinations of the form
rsync://[USER@]HOST[:PORT]/MODULE[/DIRECTORY]
(using an rsync daemon connection).
-
rsync_system_backup.destinations.
DESTINATION_PATTERNS
= [<_sre.SRE_Pattern object>, <_sre.SRE_Pattern object>, <_sre.SRE_Pattern object>, <_sre.SRE_Pattern object>]¶ A list of compiled regular expression patterns to match destination expressions. The patterns are ordered by decreasing specificity.
-
class
rsync_system_backup.destinations.
Destination
(**kw)[source]¶ The
Destination
class represents a location where backups are stored.The
expression
property is a required property whose value is parsed to populate the values of theusername
,hostname
,port_number
,module
anddirectory
properties.When you read the value of the
expression
property you get back a computed value based on the values of the previously mentioned properties. This makes it possible to manipulate the destination before passing it on to rsync.When you initialize a
Destination
object you are required to provide a value for theexpression
property. You can set the values of thedirectory
,expression
,hostname
,module
,parent_directory
,port_number
,ssh_tunnel
andusername
properties by passing keyword arguments to the class initializer.Here’s an overview of the
Destination
class:Superclass: PropertyManager
Special methods: __enter__()
and__exit__()
Properties: directory
,expression
,hostname
,module
,parent_directory
,port_number
,ssh_tunnel
andusername
-
expression
[source]¶ The destination in rsync’s command line syntax (a string).
Raises: InvalidDestinationError
when you try to set this property to a value that cannot be parsed.Note
The
expression
property is arequired_property
. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named expression (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.
-
directory
[source]¶ The pathname of the directory where the backup should be written (a string).
Note
The
directory
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
hostname
[source]¶ The host name or IP address of a remote system (a string).
Note
The
hostname
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
module
[source]¶ The name of a module exported by an rsync daemon (a string).
Note
The
module
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
parent_directory
[source]¶ The pathname of the parent directory of the backup directory (a string).
Raises: ParentDirectoryUnavailable
when the parent directory can’t be determined becausedirectory
is empty or ‘/’.Note
The
parent_directory
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
port_number
[source]¶ The port number of a remote rsync daemon (a number).
When
ssh_tunnel
is set the value ofport_number
defaults toexecutor.ssh.client.SecureTunnel.local_port
, otherwise it defaults toRSYNCD_PORT
.Note
The
port_number
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
ssh_tunnel
[source]¶ A
SecureTunnel
object orNone
(defaults toNone
).Note
The
ssh_tunnel
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
username
[source]¶ The username for connecting to a remote system (a string).
Note
The
username
property is amutable_property
. You can change the value of this property using normal attribute assignment syntax. To reset it to its default (computed) value you can usedel
ordelattr()
.
-
__enter__
()[source]¶ Automatically open
ssh_tunnel
when required.
-
__exit__
(exc_type=None, exc_value=None, traceback=None)[source]¶ Automatically close
ssh_tunnel
when required
-
rsync_system_backup.exceptions
¶
Custom exceptions used by rsync-system-backup.
-
exception
rsync_system_backup.exceptions.
RsyncSystemBackupError
[source]¶ Base exception for custom exceptions raised by rsync-system-backup.
-
exception
rsync_system_backup.exceptions.
UnsupportedPlatformError
[source]¶ Raised when an unsupported (non-Linux) platform is detected.
-
exception
rsync_system_backup.exceptions.
InvalidDestinationError
[source]¶ Raised when the given destination expression can’t be parsed.
-
exception
rsync_system_backup.exceptions.
MissingBackupDiskError
[source]¶ Raised when the encrypted filesystem isn’t available.
-
exception
rsync_system_backup.exceptions.
FailedToUnlockError
[source]¶ Raised when cryptdisks_start fails to unlock the encrypted device.
-
exception
rsync_system_backup.exceptions.
FailedToMountError
[source]¶ Raised when mount fails to mount the backup destination.
Raised when snapshot creation and rotation are disabled because we’re connected to an rsync daemon.
Raised when the parent directory of the backup directory cannot be determined.
Change log¶
The change log lists notable changes to the project:
Changelog¶
The purpose of this document is to list all of the notable changes to this project. The format was inspired by Keep a Changelog. This project adheres to semantic versioning.
- Release 1.1 (2019-08-02)
- Release 1.0 (2018-05-04)
- Release 0.11 (2018-04-30)
- Release 0.10 (2018-04-30)
- Release 0.9 (2017-07-11)
- Release 0.8 (2017-06-24)
- Release 0.7 (2017-06-23)
- Release 0.6 (2017-06-23)
- Release 0.5 (2017-06-21)
- Release 0.4 (2017-06-21)
- Release 0.3 (2017-06-06)
- Release 0.2 (2017-05-06)
- Release 0.1.1 (2017-04-17)
- Release 0.1 (2017-04-14)
Release 1.1 (2019-08-02)¶
The
--multi-fs
option suggested in pull request #3 was added.This option has the opposite effect of the rsync option
--one-file-system
because rsync-system-backup defaults to running rsync with--one-file-system
and must be instructed not to using--multi-fs
.”This change was merged by cherry picking the relevant commit from the remote branch, to avoid pulling in unrelated changes (see the pull request for details).
Stop testing on Python 2.6 (because Travis CI no longer supports it and working around this would cost an unreasonable amount of time) and start testing support for Python 3.7.
Release 1.0 (2018-05-04)¶
Bug fix: SSH tunnel support actually works now :-P (backwards incompatible).
This week I switched the backups of my VPS over to rsync-system-backup. The biggest hurdle was the fact that I never finished nor tested support for SSH tunnels in rsync-system-backup which I needed now:
- The command line interface didn’t expose the functionality.
- Due to various bugs it wouldn’t have worked even if the functionality had been exposed.
The changes in this release:
- Added the
-t
,--tunnel
command line option. - Integrated SSH tunnel support provided by executor 19.3.
- Removed the
ForwardedDestination
class (this functionality has been replaced by the newDestination.ssh_tunnel
property).
Because the removal of ForwardedDestination
is backwards incompatible I’ve
decided to bump the major version number. It’s actually kind of fitting because
I’ve been using rsync-system-backup for local backups for months now and
that’s working fine; the main thing missing was indeed SSH tunnel support :-).
Release 0.11 (2018-04-30)¶
- Added support for the
-x
,--exclude
option. - Documented that
--one-file-system
is always used.
Release 0.10 (2018-04-30)¶
- Switched to the more user friendly
getopt.gnu_getopt()
. - Added this changelog, restructured the online documentation.
- Documented the
-f
,--force
option in the readme. - Integrated the use of
property_manager.sphinx
.
Release 0.9 (2017-07-11)¶
Explicitly handle unsupported platforms (by refusing to run without the
-f
, --force
option). Refer to issue #1 for more information.
Release 0.8 (2017-06-24)¶
Don’t raise an exception when notify-send
fails to deliver a desktop notification.
Release 0.7 (2017-06-23)¶
Ensure the destination directory is located under the expected mount point.
Release 0.6 (2017-06-23)¶
Incorporated the cryptdisks_start
and cryptdisks_stop
fallbacks into the how-to.
Release 0.5 (2017-06-21)¶
Gain independence from cryptdisks_start
and cryptdisks_stop
(a Debian-ism).
Release 0.4 (2017-06-21)¶
- Gracefully handle missing backup disk.
- Added a how-to to the documentation.
Release 0.3 (2017-06-06)¶
Made it possible to disable desktop notifications.
Release 0.2 (2017-05-06)¶
- Don’t render a traceback on known errors.
- Fixed broken usage message formatting.
- Document Python 3.6 compatibility.
- Changed Sphinx theme.
Release 0.1.1 (2017-04-17)¶
Changed system logging verbosity level from DEBUG to INFO.
Release 0.1 (2017-04-14)¶
Initial release (0.1, alpha).