Linux backup and restore with BorgBackup

Borg is a deduplicating backup program which also supports compression and authenticated encryption. It provides an efficient and secure way to backup data. The data deduplication technique used makes Borg suitable for daily backups since only changes are stored. The authenticated encryption technique makes it suitable for backups to not fully trusted targets.

A more detailed description of BorgBackup can be found at https://borgbackup.readthedocs.io/en/stable/index.html.

Installation

Borg is included in many Linux distributions repositories but sometimes the packaged version is quite old, and it is better to install manually. This installation is as simple as:

In the official borg releases website section you will find the latest version:

https://github.com/borgbackup/borg/releases

$ wget https://github.com/borgbackup/borg/releases/download/1.1.5/borg-linux64
$ chmod +x borg-linux64
$ mv borg-linux64 /usr/local/bin/borg

Sample script

Backup to remote computer with SSH

#!/bin/bash
#
## BEGIN CONFIG ##
HOST=$(uname -n)
OPENKM_DB="okmdb"
OPENKM_HOME="/home/openkm"
TOMCAT_HOME="$OPENKM_HOME/tomcat"
DATABASE_EXP="$OPENKM_HOME/db"
BACKUP_HOST="backup@bk-server.com"
BACKUP_DIR="/mnt/backup/$HOST"
BACKUP_REPO="${BACKUP_HOST}:${BACKUP_DIR}"
## END CONFIG ##

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

echo "Backup destination ${BACKUP_REPO}"
if (ssh ${BACKUP_HOST} "[ ! -d ${BACKUP_DIR} ]"); then
  echo "Initialize backup repository: ${BACKUP_DIR}"
  ssh ${BACKUP_HOST} "mkdir -p ${BACKUP_DIR}"
  borg init -e none ${BACKUP_REPO}
fi

# Database
echo "Backup MySQL databases"
mkdir -p ${DATABASE_EXP}
echo "- Backuping $OPENKM_DB..."
mysqldump --single-transaction --add-drop-table --quick ${OPENKM_DB} > ${DATABASE_EXP}/mysql_$OPENKM_DB.sql

borg create -v --stats ${BACKUP_REPO}::'{now:%Y-%m-%d_%H:%M}' ${OPENKM_HOME}
borg prune -v ${BACKUP_REPO} --list --keep-daily=7 --keep-weekly=4 --keep-monthly=6

This is an improved SSH version

#!/bin/bash

# Configuration
DATABASE_EXP="/home/openkm/db"
BACKUP_HOST="backup@bk-server.com"
BACKUP_DIR="/mnt/backup/$HOST"
BACKUP_REPO="${BACKUP_HOST}:${BACKUP_DIR}"

echo "### BEGIN: $(date +"%x %X") ###"
echo "Backup destination ${BACKUP_REPO}"
TBEGIN=$(date +"%s")

# Check if the repository is already initialized
borg list ${BACKUP_REPO} > /dev/null
RESULT=$?; if [[ ${RESULT} != 0 ]]; then
  echo "Initializing backup repository..."
  borg init -e none ${BACKUP_REPO}
fi

# Database
echo "Backup MySQL databases"
mkdir -p ${DATABASE_EXP}
MYSQL_DBS=$(mysqlshow | awk '(NR > 2) && (/[a-zA-Z0-9]+[ ]+[|]/) { print $2 }');
for DB in $MYSQL_DBS; do
  if [[ $DB != "mysql" && $DB != "test" && $DB != "information_schema" && $DB != "performance_schema" ]]; then
    echo "- Backuping $DB..."
    mysqldump --single-transaction --add-drop-table --quick ${DB} > ${DATABASE_EXP}/mysql_$DB.sql
  fi
done

borg create -v --stats ${BACKUP_REPO}::'{now:%Y-%m-%d_%H:%M}' /opt /var /etc /root /home
RESULT=$?; if [[ ${RESULT} != 0 ]]; then
  echo "****************************************************"
  echo " Backup error => exit code: ${RESULT}"
  echo "****************************************************"
fi

# Prune old backups
echo "Prune old backups"
borg prune -v --list --keep-within=30d ${BACKUP_REPO}
RESULT=$?; if [[ ${RESULT} != 0 ]]; then
  echo "****************************************************"
  echo " Backup error => exit code: ${RESULT}"
  echo "****************************************************"
fi

TEND=$(date +"%s")
TDIFF=$(($TEND-$TBEGIN))
echo "### END: $(date +"%x %X") - $(($TDIFF / 60)) mins and $(($TDIFF % 60)) secs ###"

Backup to mapped network

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

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

# 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

# Initialize repository
echo "Backup destination ${BACKUP_REPO}"
if ! ls -l ${BACKUP_DIR} | grep '^d' | grep "${HOST}" > /dev/null; then
  echo "Initialize backup repository: ${BACKUP_REPO}"
  mkdir ${BACKUP_REPO}
  borg init -e none ${BACKUP_REPO}
fi

# Database
echo "Backup MySQL databases"
mkdir -p ${DATABASE_EXP}
echo "- Backuping $OPENKM_DB..."
mysqldump --single-transaction --add-drop-table --quick ${OPENKM_DB} > ${DATABASE_EXP}/mysql_$OPENKM_DB.sql

# Data backup
echo "File system backup: ${BACKUP_REPO}"
borg create -v --stats ${BACKUP_REPO}::'{now:%Y-%m-%d_%H:%M}' ${OPENKM_HOME}
borg prune -v ${BACKUP_REPO} --list --keep-daily=7 --keep-weekly=4 --keep-monthly=6

# Umount disk
sync
umount "$BACKUP_DIR"
echo "$BACKUP_DIR umounted";

Configure crontab

To install the cron job, run:

$ sudo mkdir /root/logs

$ sudo crontab -e

And add these lines according to your personal configuration:

MAILTO=nomail@openkm.com
PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin
@daily /root/backup.sh 2>&1 | 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 "postfix" service in your server.

Recovery

In order to  list all stored backup use the list action parameter:

$ borg list backup@bk-server.com:/mnt/backup/name

2018-02-07 Thu, 2018-02-07 10:12:31 [c878b314107c76b2d86ba75a9e5b2a216bf1f0d6b824313396c51ccda02a72e6]
2018-02-08 Thu, 2018-02-08 10:15:45 [2cf11f13bc7a2c9c0f1a0c243da52ac4b7657e7c6429cca0bf06a80467837f1e]

If you want to list all files in a given backup:

$ borg list backup@bk-server.com:/mnt/backup/name::2018-02-07_09:27

In case you need to access the contents of a backup you can mount as a local filesystem:

$ mkdir /tmp/backup

$ borg mount backup@bk-server.com:/mnt/backup/name::2018-02-07_09:27 /tmp/backup

If you do not specify an specific backup then will be mounted all the backup. The command line should be:

$ mkdir /tmp/backup
$ borg mount backup@bk-server.com:/mnt/backup /tmp/backup

At the end you might be interested in umount the folder

borg umount /tmp/backup