cloud-backup/templates/opt/backup/inst/cloud-server-backup.j2

276 lines
8.3 KiB
Django/Jinja

#!/bin/bash
BORGUSER="{{ backup_owner }}";
TARGETFOLDER="{{ backup_remotes_folder }}";
LOCALREPOLOCATION="{{ backup_location }}/{{ backup_app }}";
APPLIST="{{ backup_clients | json_query('*.app') | join(' ') }}";
declare -A BORG_CLIENT_MAP
{% for client in backup_clients %}
BORG_CLIENT_MAP[{{ backup_clients[client].app }}]="{{ client }}";
{% endfor %}
declare -A BORG_USER_MAP
{% for client in backup_clients %}
BORG_USER_MAP[{{ backup_clients[client].app }}]="{{ backup_clients[client].owner }}";
{% endfor %}
help (){
echo "cloud-server-backup - backup and restore script on cloud backup with borg target v1.0 by L.Hahn.
Usage: $0 COMMAND [APPS]
COMMAND:
- remote-apps-list List available apps in remote borg repositories.
- remote-list [APPS] List available archives for apps in remote borg repositories.
- remote-prune [APPS] Prune remote app (or all) borg repositories.
- list List available archives of remote repositories on local repository.
- backup Perform backup of remote borg repositories and create a new archive in local borg repository.
- prune Prune local borg backup of remote repositories.
- restore ARCHIVENAME [APPS] Upload backup to borg repository to restore older file states.
May turn off your application if still running.
If latest is provided as ARCHIVENAME, the latest one based on timestamp is taken.
IF ARCHIVENAME is provided, will try to download it; throws error if not found.
If APP is provided, only the mentioned app repositories are restored.
APPS: A single app or comma-separated (sub-)set of below listed apps to be considered.
{% for client in backup_clients %}
- {{ backup_clients[client].app }}
{% endfor %}
";
}
###############################################################################
#=== HELP FUNCTIONS ==========================================================#
###############################################################################
remote_delete_single_backup () {
REPOLOCATION=$1;
ARCHIVENAME=$2;
BORG_PASSPHRASE=$3;
KEYFILE=$4;
echo "Remove archive $ARCHIVENAME";
sudo -H -u $BORGUSER bash -c '
ARCHIVENAME='$ARCHIVENAME';
export BORG_PASSPHRASE='$BORG_PASSPHRASE';
KEYFILE='$KEYFILE';
REPOLOCATION='$REPOLOCATION';
borg delete $REPOLOCATION::$ARCHIVENAME --rsh "/usr/bin/ssh -i $KEYFILE"';
}
remote_free_space () {
REPOLOCATION=$1;
KEYFILE=$2;
APP=$3;
echo "Free space on repository for app '$APP'.";
sudo -H -u $BORGUSER bash -c '
KEYFILE='$KEYFILE';
REPOLOCATION='$REPOLOCATION';
borg compact $REPOLOCATION --rsh "/usr/bin/ssh -i $KEYFILE"';
}
has_argument () {
if [[ -z "$1" ]];
then
echo "Missing required paramter!";
exit 1;
fi
}
validate_apps_or_default () {
VALID=1;
if [[ -z "$1" ]];
then
echo $APPLIST;
else
CHECKLIST=$(echo $1 | tr ',' ' ');
for APP in $CHECKLIST;
do
if [[ ! ${APPLIST[@]} =~ $APP ]]
then
VALID=0;
echo "$APP is not a valid app.";
fi
done
if [[ ! $VALID == 1 ]]
then
echo "Aborting.";
exit 1;
else
echo $CHECKLIST;
fi
fi
}
###############################################################################
#=== USECASE FUNCTIONS =======================================================#
###############################################################################
remote_list_app () {
for APP in $APPLIST;
do
echo $APP;
done
}
remote_list () {
REMOTELIST=$1;
for APP in $REMOTELIST;
do
REPOSITORYCLIENT=${BORG_CLIENT_MAP[$APP]}
BORG_REPO_USER=${BORG_USER_MAP[$APP]}
REPOLOCATION="ssh://$BORG_REPO_USER@{{ backup_host }}:{{ backup_ssh_port }}/./$APP"
BORG_PASSPHRASE=$(cat {{ backup_key_folder }}/$APP)
KEYFILE="{{ backup_home }}/.ssh/$REPOSITORYCLIENT"
ARCHIVEIDS=$(
sudo -H -u $BORGUSER bash -c '
export BORG_PASSPHRASE='$BORG_PASSPHRASE';
KEYFILE='$KEYFILE';
REPOLOCATION='$REPOLOCATION';
borg list $REPOLOCATION --rsh "/usr/bin/ssh -i $KEYFILE"' | sort -r
);
echo "$ARCHIVEIDS";
done
}
remote_prune () {
REMOTEPRUNELIST=$1;
for APP in $REMOTEPRUNELIST;
do
BORG_REPO_USER=${BORG_USER_MAP[$APP]}
BORG_PASSPHRASE=$(cat {{ backup_key_folder }}/$APP)
REPOLOCATION="ssh://$BORG_REPO_USER@{{ backup_host }}:{{ backup_ssh_port }}/./$APP"
KEYFILE="{{ backup_home }}/.ssh/${BORG_CLIENT_MAP[$APP]}"
sudo -H -u $BORGUSER bash -c '
KEYFILE='$KEYFILE';
REPOLOCATION='$REPOLOCATION';
export BORG_PASSPHRASE='$BORG_PASSPHRASE';
borg prune -H 24 -d 7 -w 4 -m -1 -y 100 $REPOLOCATION --rsh "/usr/bin/ssh -i $KEYFILE"';
remote_free_space $REPOLOCATION $KEYFILE $APP;
done
}
local_list () {
ARCHIVEIDS=$(
sudo -H -u $BORGUSER bash -c '
REPOLOCATION='$LOCALREPOLOCATION';
export BORG_PASSPHRASE=$(cat {{ backup_home }}/.borg.key);
borg list $REPOLOCATION' | grep {{ backup_app }} | sort -r);
echo "$ARCHIVEIDS";
}
local_prune () {
sudo -H -u $BORGUSER bash -c '
KEYFILE='$KEYFILE';
REPOLOCATION='$LOCALREPOLOCATION';
export BORG_PASSPHRASE=$(cat {{ backup_home }}/.borg.key);
borg prune -H 24 -d 7 -w 4 -m -1 -y 100 $REPOLOCATION';
echo "Free space on local repository.";
sudo -H -u $BORGUSER bash -c '
REPOLOCATION='$LOCALREPOLOCATION';
borg compact $REPOLOCATION';
}
local_backup () {
ARCHIVENAME="{{ backup_app }}-$(date '+%s')";
mkdir -p $TARGETFOLDER/$ARCHIVENAME;
chown $BORGUSER: $TARGETFOLDER/$ARCHIVENAME;
for APP in $APPLIST;
do
sudo -H -u $BORGUSER bash -c '
TARGETFOLDER='$TARGETFOLDER';
ARCHIVENAME='$ARCHIVENAME';
REPOLOCATION='${BORG_CLIENT_MAP[$APP]}':'$APP';
rsync -azr $REPOLOCATION $TARGETFOLDER/$ARCHIVENAME/;';
done
sudo -H -u $BORGUSER bash -c '
TARGETFOLDER='$TARGETFOLDER';
REPOLOCATION='$LOCALREPOLOCATION';
ARCHIVENAME='$ARCHIVENAME';
export BORG_PASSPHRASE=$(cat {{ backup_home }}/.borg.key);
borg create -C lzma $REPOLOCATION::$ARCHIVENAME $TARGETFOLDER/$ARCHIVENAME;';
rm -rf $TARGETFOLDER/$ARCHIVENAME;
}
local_delete () {
ARCHIVENAME=$1;
ARCHIVEIDS=$(local_list | cut -f 1 -d ' ');
if [[ "$ARCHIVEIDS" != *$ARCHIVENAME* ]];
then
echo "ERROR! Provided archivename '$ARCHIVENAME' is not part of the available archives! Aborting.";
exit 1;
fi
echo "Remove archive $ARCHIVENAME";
sudo -H -u $BORGUSER bash -c '
ARCHIVENAME='$ARCHIVENAME';
export BORG_PASSPHRASE='$(cat {{ backup_home }}/.borg.key)';
REPOLOCATION='$LOCALREPOLOCATION';
borg delete $REPOLOCATION::$ARCHIVENAME';
}
###############################################################################
#=== MAIN FUNCTIONS ==========================================================#
###############################################################################
(
flock -n 9 || {
echo "BACKUP ALREADY RUNNING! ABORTING.";
exit 1;
}
if [ $# = 0 ]; then
help;
exit 0;
fi
action=$1
case $action in
"remote-apps-list")
remote_list_app;
;;
"remote-list")
USERLIST=$(validate_apps_or_default "$2");
remote_list "$USERLIST";
;;
"remote-prune")
USERLIST=$(validate_apps_or_default "$2");
remote_prune "$USERLIST";
;;
"list")
local_list;
;;
"prune")
local_prune;
;;
"backup")
local_backup;
;;
"restore")
has_argument $2;
USERLIST=$(validate_apps_or_default $3);
#local_restore $2;
;;
"delete")
has_argument $2;
local_delete $2;
;;
*)
help;
exit 0;
;;
esac
) 9>/var/run/lock/cloud-server-backup.lock;