Linux backup and restore with the rdiff-backup tool

Rdiff-backup backs up one directory to another, possibly over a network. The target directory ends up being a copy of the source directory. However, extra reverse diffs are stored in a special subdirectory of that target directory, so you can still recover files lost some time ago.

The idea is to combine the best features of a mirror and an incremental backup. rdiff-backup also preserves subdirectories, hard links, dev files, permissions, uid/gid ownership, modification times, extended attributes, acls, and resource forks.

Also, rdiff-backup can operate bandwidth-efficiently over a pipe, like rsync. Thus, you can securely use rdiff-backup and ssh to back up a hard drive to a remote location, and only the differences will be transmitted.  

If you need to back up to CIFS (SMB, Samba) or Mac's HFS, please look at the rdiff-backup FAQ.

Debian & Ubuntu

This utility is included in the software repository, so to install, just run as root:

$ apt-get install rdiff-backup


Rdiff-backup from Debian issues a warning message due to a deprecated method [os.popen2 is deprecated], which can be hidden following the steps in How to shut up Python deprecation warnings.

CentOS & RedHat

In this case, the application is not included in the default software repository, so you need to make use of the EPEL repository:

$ rpm -Uvh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm

$ yum update

$ yum install rdiff-backup

Preliminaries

In these scripts, the following default values are assumed:

  • $TOMCAT_HOME value is "/home/openkm/tomcat-9.0.76"
  • OpenKM database is named "okmdb."
  • OpenKM database password value is "*secret*".
  • OpenKM start & stop service script location is "/etc/init.d/tomcat"

Sample script

As a good practice, the root user should do the backup.

The script below does a backup to USB, and the application database is MySQL.

The USB disk mount point can be defined in /etc/fstab as:

/dev/sdb1    /mnt/backup    ext4    defaults    0    0

These are the global script sections:

  • Global var configuration under the ## BEGIN CONFIG ## section.
  • Checking the root user under the # Check root section.
  • Deleting older database backups in the # Delete older local database backup  section.
  • Mount disk (optional section) under the # Mount disk section.
  • Stop the application (optional section) under  # Stop tomcat section.
  • Clean logs (optional section) under the # Clean logs section.
  • Backup the database to the filesystem under the # Backup database section.
  • Backup the repository and database dump to the backup destination under the # Backup and purge old backups section.
  • Start the application (optional section) under the # Start tomcat section.
  • Show statistics (optional section) under the # Status section.
  • Umount disk (optional section) under the # Umount disk section.

Explanation of configuration parameters:

ParameterDescription

HOST

The server hostname.

DATABASE_PASS

The database password.

The database user who performs the backup is always the root user.

OPENKM_DB

The application database name.

Usually, it will be named "okmdb".

OPENKM_HOME

The OpenKM home folder.

TOMCAT_HOME

The Tomcat home folder.

Usually in the OPENKM_HOME folder.

DATABASE_EXP

The database dump folder.

Usually on the same server.

BACKUP_DIR

 Backup destination. In the case of a remote server, the format is user@server::/path/to/backup

Create a backup script /root/backup.sh

$ sudo su

$ vim /root/backup.sh

#!/bin/bash
#
## BEGIN CONFIG ##
HOST=$(uname -n)
DATABASE_PASS="*secret*"
OPENKM_DB="okmdb"
OPENKM_HOME="/home/openkm"
TOMCAT_HOME="$OPENKM_HOME/tomcat-9.0.76"
DATABASE_EXP="$OPENKM_HOME/db"
BACKUP_DIR="/mnt/backup"
## END CONFIG ##

# Check root user 
if [ $(id -u) != 0 ]; then echo "You should run this script as root"; exit; fi

# Delete older local database backup  
echo -e "### BEGIN: $(date +"%x %X") ###\n"
rm -rf $DATABASE_EXP
mkdir -p $DATABASE_EXP
 
# Mount disk
if mount | grep "$BACKUP_DIR type" > /dev/null; then
  echo "$BACKUP_DIR already mounted";
else
  mount "$BACKUP_DIR";
if mount | grep "$BACKUP_DIR type" > /dev/null; then echo "$BACKUP_DIR mounted"; else echo "$BACKUP_DIR error mounting"; exit -1; fi fi # Stop Tomcat /etc/init.d/tomcat stop # Clean logs #echo "Clean Tomcat temporal files." #rm -rf $TOMCAT_HOME/logs/* #rm -rf $TOMCAT_HOME/temp/* #rm -rf $TOMCAT_HOME/work/Catalina/localhost # Backup database if [ -n "$DATABASE_PASS" ]; then echo "* Backuping MySQL data from $OPENKM_DB..." mysqldump -h localhost -u root -p$DATABASE_PASS $OPENKM_DB > $DATABASE_EXP/mysql_$OPENKM_DB.sql echo "-------------------------------------"; fi # Backup and purge old backups rdiff-backup --remove-older-than 30B $BACKUP_DIR/$HOST rdiff-backup -v 3 --print-statistics --include $OPENKM_HOME --exclude '**' / $BACKUP_DIR/$HOST # Start Tomcat /etc/init.d/tomcat start echo -e "\n### END: $(date +"%x %X") ###" # Status echo "================================="; rdiff-backup --list-increment-sizes $BACKUP_DIR/$HOST echo "*********************************"; df -h | grep "$BACKUP_DIR" echo "================================="; # Umount disk sync umount "$BACKUP_DIR"

Increase the backup period

Modify the # Backup and purge old backups section to increase the parameter value:

The "30B" value indicates that you can restore a full backup from any of the last 30 days; increasing it to "90B" will allow restoring from any of the previous 90 days, etc.

--remove-older-than 90B

Do a remote backup

Modify the # Backup and purge old backups section.

The backup@server indicates the remote "server" accessed by the user "backup".

# Backup and purge old backups
rdiff-backup --remove-older-than 30B backup@server::$BACKUP_DIR/$HOST
rdiff-backup -v 3 --print-statistics --include $FILES --exclude '**' / backup@server::$BACKUP_DIR/$HOST

Also, you could modify only the ## Config section, for example:

## BEGIN CONFIG ##
BACKUP_DIR="user@server::/path/to/backup"

And keep the # Backup and purge old backups intact.

# Backup and purge old backups
rdiff-backup --remove-older-than 30B $BACKUP_DIR/$HOST

Do a remote backup to SMB or CIFS

Modify the # Mount disk section.

# Mount disk
if mount | grep "$BACKUP_DIR type" > /dev/null; then
  echo "$BACKUP_DIR already mounted";
else
  echo "Mounting $BACKUP_DIR ...";
  mount -t cifs //REMOTE_SERVER/REMOTE_DIR $BACKUP_DIR -o username=REMOTE_USER,password=REMOTE_PASSWORD,iocharset=utf8,file_mode=0777,dir_mode=0777
if mount | grep "$BACKUP_DIR type" > /dev/null; then echo "$BACKUP_DIR mounted"; else echo "Error mounting $BACKUP_DIR."; exit -1; fi fi

Do a PostgreSQL backup

Modify the # Backup database section.

# Backup de PostgreSQL
echo "* Backuping PostgreSQL data from $OPENKM_DB..."
su postgres -c "pg_dump $OPENKM_DB" > $DATABASE_EXP/pg_$OPENKM_DB.sql
 
# Databases optimizations
su postgres -c "vacuumdb -a -z" > /dev/null
su postgres -c "reindexdb -a -q" 2> /dev/null

Configure crontab

To install the cron job, run the following:

$ sudo mkdir /root/logs

$ sudo crontab -e

And add these lines according to your configuration:

MAILTO=nomail@openkm.com
@daily /root/backup.sh | tee /root/logs/backup.$(date +\%Y.\%m.\%d_\%H.\%M.\%S).log

More information at Crontab quick reference

If you want to be notified by mail, you should install the "postfix" service on your server.

Restoring a backup

You can list the available backups:

$ rdiff-backup --list-increment-sizes /path/to/backup
Sun Sep 11 05:00:19 2012         4.25 GB           4.25 GB   (current mirror)
Sun Sep  4 00:00:18 2012         13.3 MB           4.26 GB
Sun Aug 28 00:00:13 2012          674 MB           4.92 GB
Sun Aug 21 00:00:14 2012         5.50 MB           4.93 GB
Sun Aug 14 00:00:16 2012         1.75 MB           4.93 GB
Sun Aug  7 00:00:12 2012          288 KB           4.93 GB
Sun Jul 31 00:00:13 2012         43.0 KB           4.93 GB
Fri Jul 29 10:36:39 2012         5.56 KB           4.93 GB

Then decide to restore one of the backups, for example, the one made on Sun Aug 28 00:00:13 2012:

$ rdiff-backup --restore-as-of 2012-08-28 /path/to/backup /path/to/destination

Or restore the last backup.

$ rdiff-backup --restore-as-of now /path/to/backup /path/to/destination

The --restore-as-of parameter accepts several formats. See rdiff-backup documentation for more info.

Sample for restoring a single folder (the /home/openkm/tomcat-9.0.76/ must exist)

rdiff-backup --restore-as-of now /mnt/backup/ms1/home/openkm/tomcat-9.0.76/ /home/openkm/tomcat-8.5.69/

Inside /path/to/destination, you should see a directory /home/openkm, and inside it, a couple of directories:

  • db: The backup of the database.
  • tomcat-9.0.76: The backup of the Tomcat installation and OpenKM repository.

Additional information