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 by 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

These scripts assume the following default values:

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

Sample script

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

The script below performs a backup to a USB drive, 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 variable configuration in the ## BEGIN CONFIG ## section.
  • Checking for the root user in the # Check root section.
  • Deleting older local database backups in the # Delete older local database backup section.
  • Mount disk (optional section) in the # Mount disk section.
  • Stop application (optional section) in the # Stop tomcat section.
  • Clean logs (optional section) in the # Clean logs section.
  • Backup the database to the filesystem in the # Backup database section.
  • Backup the repository and database dump to the backup destination in the # Backup and purge old backups section.
  • Start application (optional section) in the # Start tomcat section.
  • Show statistics (optional section) in the # Status section.
  • Umount disk (optional section) in 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 inside 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-8.5.69"
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 any of the previous 90 days, etc.

--remove-older-than 90B

Do 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

You could also 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 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 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 the rdiff-backup documentation for more information.

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

rdiff-backup --restore-as-of now /mnt/backup/ms1/home/openkm/tomcat-8.5.69/ /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-8.5.69: The backup of the Tomcat installation and OpenKM repository.

Additional information