#!/bin/bash BORGUSER="{{ backup_owner }}"; RUNFOLDER="{{ backup_storage }}"; 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; BORG_USER=$4; KEYFILE=$5; sudo -H -u $BORG_USER bash -c ' ARCHIVENAME='$ARCHIVENAME'; export BORG_PASSPHRASE='$BORG_PASSPHRASE'; KEYFILE='$KEYFILE'; REPOLOCATION='$REPOLOCATION'; borg delete $REPOLOCATION::$ARCHIVENAME --rsh "/usr/bin/ssh -i $KEYFILE"'; } ############################################################################### #=== 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 ARCHIVLIST=$(remote_list $APP | cut -f 1 -d ' '); echo "$ARCHIVLIST" > {{ backup_inst }}/backuplist.txt; DELETELIST=$(python3 {{ backup_inst }}/filter_backups.py -f {{ backup_inst }}/backuplist.txt -d;) REPOLOCATION="ssh://$BORG_REPO_USER@{{ backup_host }}:{{ backup_ssh_port }}/./$APP" BORG_PASSPHRASE=$(cat {{ backup_key_folder }}/$APP) BORG_REPO_USER=${BORG_USER_MAP[$APP]} KEYFILE="{{ backup_home }}/.ssh/${BORG_CLIENT_MAP[$APP]}" for DELETEBACKUP in $DELETELIST; do echo "remote_delete_single_backup $REPOLOCATION $DELETEBACKUP $BORG_PASSPHRASE $BORG_REPO_USER $KEYFILE" done done } 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 } ( 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;