Backup script for Linux servers utilizing Borg Backup https://decatec.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
6.0 KiB

#!/bin/bash
#
# Backup Script for Linux servers
#
# This script needs to be customized to fit your needs. Most important are the folder and applications which should be part of the backup.
# The folders to backup are specified in the variable $borgBackupDirs (see below)
# Besides these folders, Nextcloud (https://nextcloud.com/) is taken as example for an additional web application which should be included in the backup.
#
# Required software and scripts:
# - Borg Backup (https://www.borgbackup.org/)
# - When Nextcloud backup should be included: Nextcloud Backup/Restore scrips (https://codeberg.org/DecaTec/Nextcloud-Backup-Restore)
#
# Remarks
# - The borg repository has to be set up before the script is called.
#
# IMPORTANT
# You have to customize this script (directories, users, etc.) for your actual environment.
# All entries which need to be customized are tagged with "TODO".
#
#
# Calling via cron:
# - crontab -e: Every night at 02:05
# m h dom mon dow command
# 5 2 * * * /home/user/scripts/server_backup.sh > /dev/null 2>&1
#
# Make sure the script exits when any command fails
set -Eeuo pipefail
#
# Environment variables
#
# TODO: The borg repository's password
export BORG_PASSPHRASE='passw0rd'
# This has to be set when the repository has been created by user and the script is called by cron
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
# For "Warning: The repository at location ... was previously located at ..."
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
#
# Variables
#
# Compression. Borg uses "lz4" by default.
# Call 'borg help compression' to learn about other compression algorithms, e.g. "zlib,6" provides a medium compression with medium compression speed.
compression="lz4"
startTime=$(date +%s)
currentDate=$(date --date @"$startTime" +"%Y%m%d_%H%M%S")
currentDateReadable=$(date --date @"$startTime" +"%d.%m.%Y - %H:%M:%S")
# TODO: Customize according to your needs
logDirectory="/home/user/backup_logs/server_backup"
logFile="${logDirectory}/server-backup-${currentDate}.log"
# TODO: This is the local backup dir where the local backups (e.g. Nextcloud) are stored before being backuped by borg backup.
localBackupDir="/media/hdd1/backups_local_temp"
# TODO: Mount point of the backup destination folder
backupDiskMount="/media/hdd2"
# TODO: This is the dir where the borg respository is stored
borgRepository="${backupDiskMount}/server_backup/borg"
# TODO: List of (local) dirs borg should backup
borgBackupDirs="/var/www/ /etc/ /home/user/ /media/hdd1/NetworkShares/ $localBackupDir/"
# Nextcloud
localNextcloudBackupDir="${localBackupDir}/nextcloud"
# TODO: To be excluded by borg (the Nextcloud web directory)
nextcloudDirBorgExclude="/var/www/nextcloud"
#
# Create log dir if it does not exist already
#
if [ ! -d "${logDirectory}" ]
then
mkdir -p "${logDirectory}"
fi
# Function for error messages
errorecho() { cat <<< "$@" 1>&2; }
#
# Write output to logfile. Comment following lines in order to see output on terminal.
#
exec > >(tee -i "${logFile}")
exec 2>&1
#
# Preparation
#
# Check for root
if [ "$(id -u)" != "0" ]
then
errorecho "ERROR: This script has to be run as root!"
exit 1
fi
#
# Check if directories already exist
#
# Local backup directory
if [ ! -d "${localBackupDir}" ]
then
mkdir -p "${localBackupDir}"
fi
# Nextcloud
if [ ! -d "${localNextcloudBackupDir}" ]
then
mkdir -p "${localNextcloudBackupDir}"
fi
echo -e "\n###### Starting server backup on ${currentDateReadable} ######\n"
#
# Create a list with installed software
#
echo -e "\n######"
echo -e "\n$(date +"%H:%M:%S"): Create a list with installed software"
dpkg --get-selections > "${localBackupDir}/software.list"
echo -e "\nDone\n"
echo -e "######\n"
#
# Backup Nextcloud
#
# TODO: Storage location of the script
echo -e "\n######"
echo -e "\n$(date +"%H:%M:%S"): Backup Nextcloud"
/bin/bash /home/user/scripts/NextcloudBackup.sh ${localNextcloudBackupDir}
echo -e "\nDone\n"
echo -e "######\n"
#
# Backup with borg
#
echo -e "\n######"
echo -e "\n$(date +"%H:%M:%S"): Backup with Borg"
# The backup is created with two main parts:
# - The backups created separately (in this example Nextcloud)
# - Backup of the important directories of the system.
#
# Remarks
# - Do not add "--progress" when calling the script by cron!
borg create --stats \
--compression "${compression}" \
$borgRepository::"${currentDate}" \
$borgBackupDirs \
--exclude $nextcloudDirBorgExclude
echo -e "\nDone\n"
echo -e "######\n"
#
# Cleanup
#
echo -e "\n\n###### Cleanup backup ######"
# All local backups are deleted again, as they were saved by borg backup
# Delete list of installed software
echo -e "\n######"
echo -e "\n$(date +"%H:%M:%S"): Delete list of installed software"
rm "${localBackupDir}"/software.list
echo -e "\nDone\n"
echo -e "######\n"
# Delete local Nextcloud backup
echo -e "\n######"
echo -e "\n$(date +"%H:%M:%S"): Delete local Nextcloud backup"
rm -r "${localNextcloudBackupDir:?}"/*
echo -e "\nDone\n"
echo -e "######\n"
# Borg prune
echo -e "\n######"
echo -e "\n$(date +"%H:%M:%S"): Cleanup borg backups"
# TODO: Borg should keep backups from the last 7 days (one week), 4 weekly backups (one month) and 6 monthly backups (half a year)
borg prune --progress --stats $borgRepository \
--keep-within=7d \
--keep-weekly=4 \
--keep-monthly=6
echo -e "\nDone\n"
echo -e "######\n"
#
# Misc
#
# Duration of backup
endTime=$(date +%s)
endDateReadable=$(date --date @"$endTime" +"%d.%m.%Y - %H:%M:%S")
duration=$((endTime-startTime))
durationSec=$((duration % 60))
durationMin=$(((duration / 60) % 60))
durationHour=$((duration / 3600))
durationReadable=$(printf "%02d hours %02d minutes %02d seconds" $durationHour $durationMin $durationSec)
echo -e "\n\n###### Server backup finished on ${endDateReadable} (${durationReadable}) ######\n"
# Free space on backup disk
echo -e "\nDisk usage:\n"
df -h ${backupDiskMount}
#
# Send mail to admin
#
# Important: An MTA has to be installed for sending mails.
# TODO: Add your own e-mail address here.
mail -s "Server backup finished" my@email.address < "${logFile}"