ckupeye/backup.sh

231 lines
6 KiB
Bash
Executable file

#!/usr/bin/env bash
################################
# ckupeye executable #
# (Frogeye's backup script v4) #
################################
#
# Load config file
#
CLIENT_CONFIG_FILE="${1:-/etc/ckupeye/config.sh}"
if [ -f "$CLIENT_CONFIG_FILE" ]
then
. "$CLIENT_CONFIG_FILE"
else
echo "Configuration file not found on $CLIENT_CONFIG_FILE."
exit 1
fi
#
# Required configuration
#
if [ -z ${BORG_REPO+x} ]
then
echo "Please specify BORG_REPO in the configuration file."
echo "See https://borgbackup.readthedocs.io/en/stable/usage/general.html?highlight=borg_repo#repository-urls"
exit 1
fi
if [[ -z ${BORG_PASSPHRASE+x} && -z ${BORG_PASSCOMMAND+x} && -z ${BORG_PASSPHRASE_FD+x} ]]
then
echo "Please specify one of BORG_PASSPHRASE, BORG_PASSCOMMAND or BORG_PASSPHRASE_FD in the configuration file."
echo "See https://borgbackup.readthedocs.io/en/stable/man_intro.html?highlight=borg_passphrase#environment-variables"
exit 1
fi
#
# Default configuration
#
: "${BASE_DIR:="/var/ckupeye"}"
# Directories to backup
[ -z ${BACKUP_FILES+x} ] && BACKUP_FILES=("/") # What to include in the backup
[ -z ${BACKUP_EXCLUDES+x} ] && BACKUP_EXCLUDES=("/var/cache" "**.lock" "**/.cache/") # What to exclue from the backup
: "${BACKUP_TAG:="$(date -Isec)"}" # “Name” of the backup
: "${BACKUP_OPTIONS:="--one-file-system --compression auto,zstd"}" # Configuration of the backup
# Default folder where the database / package managers / ACL exported data will be stored.
: "${EXPORT_DIR:="$BASE_DIR"}"
# Things to export the data of
: "${EXPORT_MARIADB:="false"}"
: "${EXPORT_POSTGRESQL:="false"}"
: "${EXPORT_APT:="false"}"
: "${EXPORT_PACMAN:="false"}"
: "${EXPORT_ACL:="false"}"
: "${EXPORT_ETCKEEPER:="false"}"
# Where to put the exported data
: "${EXPORT_MARIADB_FILE:="$EXPORT_DIR/mariadb.sql"}"
: "${EXPORT_POSTGRESQL_FILE:="$EXPORT_DIR/postgresql.sql"}"
: "${EXPORT_APT_FILE:="$EXPORT_DIR/apt.list"}"
: "${EXPORT_PACMAN_FILE:="$EXPORT_DIR/pacman.list"}"
: "${EXPORT_ACL_FILE:="$EXPORT_DIR/acl.list"}"
# Options for exporting data
[ -z ${EXPORT_ACL_DIRECTORIES+x} ] && EXPORT_ACL_DIRECTORIES=("${BACKUP_FILES[@]}")
: "${EXPORT_ETCKEEPER_MESSAGE:="ckupeye backup for $(date -Isec)"}"
: "${EXPORT_POSTGRESQL_OPTIONS:=""}"
: "${EXPORT_MARIADB_OPTIONS:="--all-databases --flush-privileges"}"
: "${EXPORT_MARIADB_CREDENTIALS:="$BASE_DIR/mariadb.cnf"}"
# Pruning the backup
: "${PRUNE:="true"}"
: "${PRUNE_OPTIONS:="--keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 10"}"
# Borg specific
: "${BORG_BASE_DIR:="$BASE_DIR"}"
: "${BORG_EXECUTABLE:="$(command -v borg)"}" # Path to BorgBackup executable
: "${BORG_SSH_IDENTITY_FILE:="/etc/ckupeye/id_ed25519"}" # Identity file to use to connect to remote repo (will overwrite $BORG_RSH)
: "${BORG_RSH_EXTRA:=""}" # Options to add to $BORG_RSH (even after overriden by BORG_SSH_IDENTITY_FILE)
: "${BORG_OPTIONS:=""}" # Additional options to pass to BorgBackup
: "${BORG_ENCRYPTION:="repokey-blake2"}" # Passed `borg init`
# Answer borg questions
: "${BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK:=no}"
: "${BORG_RELOCATED_REPO_ACCESS_IS_OK:=no}"
: "${BORG_CHECK_I_KNOW_WHAT_I_AM_DOING:=NO}"
: "${BORG_DELETE_I_KNOW_WHAT_I_AM_DOING:=NO}"
: "${BORG_RECREATE_I_KNOW_WHAT_I_AM_DOING:=NO}"
# Ckupeye specific
: "${CLIENT_RUNFILE:="$BASE_DIR/ckupeye.pid"}"
# Export borg environment variables
export BORG_REPO
export BORG_PASSPHRASE
export BORG_PASSCOMMAND
export BORG_PASSPHRASE_FD
export BORG_BASE_DIR
# this should be done in the configuration file too,
# for consistency
#
# Preparation
#
if [ -e $CLIENT_RUNFILE ] && ps -p $(cat $CLIENT_RUNFILE) > /dev/null
then
echo "Another backup instance is running. Skipping"
exit 1
fi
if ! touch $CLIENT_RUNFILE
then
echo "Could not create a runfile on $CLIENT_RUNFILE. Please change CLIENT_RUNFILE according to this user's permissions."
exit 1
fi
echo $$ > $CLIENT_RUNFILE
#
# Test repository, create it if not present
#
if [ ! -z "$BORG_SSH_IDENTITY_FILE" ]
then
export BORG_RSH="ssh -oBatchMode=yes -i $BORG_SSH_IDENTITY_FILE $BORG_RSH_EXTRA"
fi
echo "→ Opening repository"
$BORG_EXECUTABLE $BORG_OPTIONS info
if [ $? != 0 ]
then
echo "→ Could not open repository, trying to create it"
$BORG_EXECUTABLE $BORG_OPTIONS init --encryption "$BORG_ENCRYPTION"
if [ $? != 0 ]
then
echo "Could not create repository."
exit 1
fi
fi
#
# Exporting databases
#
if [ ! -z ${EXPORT_DIR+x} ]
then
mkdir -p "$EXPORT_DIR"
fi
if $EXPORT_ETCKEEPR
then
echo → Creating etckeeper commit
etckeeper commit "$EXPORT_ETCKEEPER_MESSAGE" &> /dev/null &
fi
export EXPORT_FILEs=""
function _feedExport() { # export_file
touch "$1"
chmod 700 "$1"
cat - > "$1"
export EXPORT_FILES="$1 $EXPORT_FILES"
}
if $EXPORT_ACL
then
echo → Exporting ACL
sudo getfacl -R "$EXPORT_ACL_DESTINATION[@]" 2> /dev/null | _feedExport "$EXPORT_ACL_FILE"
fi
if $EXPORT_POSTGRESQL
then
echo → Exporting PostgreSQL
pg_dumpall $EXPORT_POSTGRESQL_OPTIONS | _feedExport "$EXPORT_POSTGRESQL_FILE"
fi
if $EXPORT_MARIADB
then
echo → Exporting MariaDB
if [ ! -z $EXPORT_MARIADB_CREDENTIALS ]
then
EXPORT_MARIADB_OPTIONS="--defaults-extra-file=$EXPORT_MARIADB_CREDENTIALS $EXPORT_MARIADB_OPTIONS"
fi
mysqldump $EXPORT_MARIADB_OPTIONS | _feedExport "$EXPORT_MARIADB_FILE"
fi
if $EXPORT_PACMAN
then
echo → Exporting Pacman package list
pacman -Qeq | _feedExport "$EXPORT_PACMAN_FILE"
fi
if $EXPORT_APT
then
echo → Exporting Apt package list
apt list --installed 2> /dev/null | _feedExport "$EXPORT_APT_FILE"
fi
echo "→ Transfering files"
for exclude in "${BACKUP_EXCLUDES[@]}"
do
BACKUP_OPTIONS="$BORG_CREATE_OPTIONS --exclude=$exclude"
done
$BORG_EXECUTABLE $BORG_OPTIONS create --stats $BACKUP_OPTIONS "${BORG_REPO}::${BACKUP_TAG}" ${BACKUP_FILES[@]} 2>&1
echo "→ Remove temporary files"
rm -f $EXPORT_FILES
if $PRUNE
then
echo "→ Pruning old backups"
$BORG_EXECUTABLE $BORG_OPTIONS prune --stats $PRUNE_OPTIONS $BORG_REPO 2>&1
fi
echo "→ Done!"
rm "$CLIENT_RUNFILE"