Added support for Synology NAS systems

This commit is contained in:
Enrico Ludwig 2024-05-13 12:51:49 +02:00
parent 0dbe3e8d48
commit ef25e70b59

View File

@ -24,7 +24,6 @@
# Planned Features: # Planned Features:
# - Add support for more distributions # - Add support for more distributions
# - Add support for automatic setup (non-interactive)
# SETTINGS - Make sure to adjust these settings to your needs # SETTINGS - Make sure to adjust these settings to your needs
DEBUG=0 # Set to 1 to enable debug mode DEBUG=0 # Set to 1 to enable debug mode
@ -48,6 +47,12 @@ SSH_KEY_FILE="/root/.ssh/${SSH_KEY_NAME}_${SSH_KEY_TYPE}"
# SCRIPT - DO NOT EDIT # SCRIPT - DO NOT EDIT
# internal variables
AUTO=0
NO_UPGRADE=0
FIRST_BACKUP=0
IS_REMOTE_SYNOLGY=0
# constants # constants
readonly SCRIPT_NAME="Borgmatic Backup Setup Tool" readonly SCRIPT_NAME="Borgmatic Backup Setup Tool"
readonly SCRIPT_AUTHOR="Zion Networks at admin@zion-networks.de" readonly SCRIPT_AUTHOR="Zion Networks at admin@zion-networks.de"
@ -107,6 +112,22 @@ function errp {
fi fi
} }
# logging functions that wait for user input (single key)
function infw {
echo -e -n "\e[97m[$(date +%H:%M:%S)] \e[1mINF\e[0m $1 "
read -n 1 -r
}
function wrnw {
echo -e -n "\e[93m[$(date +%H:%M:%S)] \e[1mWRN\e[0m $1 "
read -n 1 -r
}
function errw {
echo -e -n "\e[91m[$(date +%H:%M:%S)] \e[1mERR\e[0m $1 "
read -n 1 -r
}
# logging functions with follow up (like "[HH:MM:SS] INF Installig package ... OK" where OK is a follow up) # logging functions with follow up (like "[HH:MM:SS] INF Installig package ... OK" where OK is a follow up)
function inf_follow { function inf_follow {
if [ $DEBUG -eq 1 ]; then if [ $DEBUG -eq 1 ]; then
@ -120,6 +141,8 @@ function inf_follow {
${@:4} ${@:4}
_r=$? _r=$?
dbg "Follow exit status: $_r"
if [ $_r -eq 0 ]; then if [ $_r -eq 0 ]; then
if [ $DEBUG -eq 1 ]; then if [ $DEBUG -eq 1 ]; then
echo -e "\e[97m[$(date +%H:%M:%S)] \e[1mINF\e[0m $1: $2" echo -e "\e[97m[$(date +%H:%M:%S)] \e[1mINF\e[0m $1: $2"
@ -146,6 +169,8 @@ function wrn_follow {
_r=$(${@:4}) _r=$(${@:4})
dbg "Follow exit status: $_r"
if [ $_r -eq 0 ]; then if [ $_r -eq 0 ]; then
if [ $DEBUG -eq 1 ]; then if [ $DEBUG -eq 1 ]; then
echo -e "\e[93m[$(date +%H:%M:%S)] \e[1mWRN\e[0m $1: $2" echo -e "\e[93m[$(date +%H:%M:%S)] \e[1mWRN\e[0m $1: $2"
@ -170,6 +195,8 @@ function err_follow {
_r=$(${@:4}) _r=$(${@:4})
dbg "Follow exit status: $_r"
if [ $_r -eq 0 ]; then if [ $_r -eq 0 ]; then
if [ $DEBUG -eq 1 ]; then if [ $DEBUG -eq 1 ]; then
echo -e "\e[91m[$(date +%H:%M:%S)] \e[1mERR\e[0m $1: $2" echo -e "\e[91m[$(date +%H:%M:%S)] \e[1mERR\e[0m $1: $2"
@ -269,6 +296,9 @@ function run_command {
status=$? status=$?
echo "$output" | while read -r line; do dbg "$line"; done 1>&3 echo "$output" | while read -r line; do dbg "$line"; done 1>&3
exec 3>&- exec 3>&-
dbg "Command exit status: $status"
return $status return $status
} }
@ -302,6 +332,11 @@ function check_crontab {
return $? return $?
} }
function is_remote_synology {
run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" test -f /etc/synoinfo.conf
return $?
}
# main script # main script
# Available arguments: # Available arguments:
@ -390,13 +425,15 @@ while [[ $# -gt 0 ]]; do
inf "" inf ""
inf "Options:" inf "Options:"
inf " -a, --auto: Enable automatic, non-interactive mode" inf " -a, --auto: Enable automatic, non-interactive mode"
inf " -n, --no-upgrade: Skip package upgrades"
inf " -d, --debug: Enable debug mode" inf " -d, --debug: Enable debug mode"
inf " -f, --first-backup: Run the first backup after setup"
inf " -v, --version: Show script version" inf " -v, --version: Show script version"
inf " -h, --help: Show help message" inf " -h, --help: Show help message"
inf "" inf ""
inf " -R, --repo: Set the backup repository path" inf " -R, --repo: Set the backup repository path"
inf " -E, --encryption: Set the encryption method" inf " -E, --encryption: Set the encryption method"
inf " -P, --passphrase: Set the backup passphrase" inf " -P, --passphrase: Set the backup passphrase (if set but empty, the script will ask for the passphrase)"
inf " -D, --dirs: Set the backup directories (separated by space as a string, for example: --dirs \"/etc /var/log /home\")" inf " -D, --dirs: Set the backup directories (separated by space as a string, for example: --dirs \"/etc /var/log /home\")"
inf " -L, --label: Set the backup label prefix" inf " -L, --label: Set the backup label prefix"
inf " -S, --schedule: Set the cron schedule" inf " -S, --schedule: Set the cron schedule"
@ -404,7 +441,7 @@ while [[ $# -gt 0 ]]; do
inf " -H, --host: Set the backup server hostname or IP address" inf " -H, --host: Set the backup server hostname or IP address"
inf " -P, --port: Set the backup server SSH port" inf " -P, --port: Set the backup server SSH port"
inf " -U, --user: Set the backup server SSH user" inf " -U, --user: Set the backup server SSH user"
inf " -W, --password: Set the backup server SSH password" inf " -W, --password: Set the backup server SSH password (if set but empty, the script will ask for the password)"
inf " -K, --key-name: Set the SSH key name" inf " -K, --key-name: Set the SSH key name"
inf " -T, --key-type: Set the SSH key type" inf " -T, --key-type: Set the SSH key type"
inf " -F, --key-file: Set the SSH key file path" inf " -F, --key-file: Set the SSH key file path"
@ -427,9 +464,14 @@ while [[ $# -gt 0 ]]; do
shift shift
;; ;;
-P|--passphrase) -P|--passphrase)
if [ -z $BACKUP_PASSPHRASE ]; then
BACKUP_PASSPHRASE="$2" BACKUP_PASSPHRASE="$2"
shift shift
shift shift
else
BACKUP_PASSPHRASE=""
shift
fi
;; ;;
-D|--dirs) -D|--dirs)
BACKUP_DIRS="$2" BACKUP_DIRS="$2"
@ -462,9 +504,14 @@ while [[ $# -gt 0 ]]; do
shift shift
;; ;;
-W|--password) -W|--password)
if [ -z $SSH_PASSWORD ]; then
SSH_PASSWORD="$2" SSH_PASSWORD="$2"
shift shift
shift shift
else
SSH_PASSWORD=""
shift
fi
;; ;;
-K|--key-name) -K|--key-name)
SSH_KEY_NAME="$2" SSH_KEY_NAME="$2"
@ -516,6 +563,13 @@ wrn "This script will install \e[1mborgbackup\e[0m, \e[1mpipx\e[0m"
wrn "and \e[1msshpass\e[0m from the official repositories as well" wrn "and \e[1msshpass\e[0m from the official repositories as well"
wrn "as \e[1mborgmatic\e[0m from the official PyPI repository." wrn "as \e[1mborgmatic\e[0m from the official PyPI repository."
inf "The following settings will be used for the backup setup:"
inf "Backup repository: $BACKUP_REPO"
inf "Backup encryption: $BACKUP_ENCRYPTION"
inf "Backup directories: $BACKUP_DIRS"
inf "Backup cron schedule: $BACKUP_CRON_SCHEDULE"
inf "Backup server host: $SSH_USER@$SSH_HOST:$SSH_PORT"
# only ask for confirmation in interactive mode # only ask for confirmation in interactive mode
if [ -z $AUTO ] && ! wrnp "Do you want to continue? [y/N]"; then if [ -z $AUTO ] && ! wrnp "Do you want to continue? [y/N]"; then
inf "Aborted." inf "Aborted."
@ -609,21 +663,76 @@ if ! inf_follow "Checking for default ssh key at $SSH_KEY_FILE..." "\e[1;32mYes\
fi fi
fi fi
if ! inf_follow "Copying ssh key to $SSH_HOST..." "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command sshpass -p "$SSH_PASSWORD" ssh-copy-id -i "$SSH_KEY_FILE" -p "$SSH_PORT" -o StrictHostKeyChecking=no "$SSH_USER@$SSH_HOST"; then # check first if ssh key is already present on the remote end
if ! inf_follow "Checking if ssh key is already present on $SSH_HOST..." "\e[1;32mYes\e[0m" "\e[1;31mNo\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" exit; then
# ask for ssh password if none is set
if [ -z "$SSH_PASSWORD" ]; then
wrn "Please enter the password for the ssh key to copy it to the backup server."
wrn "This is required to enable passwordless ssh login for backups."
read -s -p "Password: " SSH_PASSWORD
echo ""
fi
if ! inf_follow "Copying ssh key to $SSH_HOST..." "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command sshpass -p "$SSH_PASSWORD" ssh-copy-id -i "$SSH_KEY_FILE" -p "$SSH_PORT" -o StrictHostKeyChecking=no "$SSH_USER@$SSH_HOST"; then
err "Failed to copy ssh key to $SSH_HOST." err "Failed to copy ssh key to $SSH_HOST."
err "Please validate your ssh password and and host settings and try again." err "Please validate your ssh password and and host settings and try again."
err "If the error persists, please contact the support at $SCRIPT_SUPPORT." err "If the error persists, please contact the support at $SCRIPT_SUPPORT."
exit 1 exit 1
else else
if ! inf_follow "Checking if ssh key is working..." "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" exit; then if ! inf_follow "Checking if ssh key is working..." "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" exit; then
err "Failed to connect to $SSH_HOST using the ssh key." err "Failed to connect to $SSH_HOST using the ssh key."
err "Please validate you have the correct ssh key and host settings." err "Please validate you have the correct ssh key and host settings."
err "If the error persists, please contact the support at $SCRIPT_SUPPORT." err "If the error persists, please contact the support at $SCRIPT_SUPPORT."
exit 1 exit 1
fi fi
fi
fi fi
if ! inf_follow "Checking if remote end has borg installed..." "\e[1;32mYes\e[0m" "\e[1;31mNo\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" borg --version; then if ! inf_follow "Checking if remote end has borg installed..." "\e[1;32mYes\e[0m" "\e[1;31mNo\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" borg --version; then
if inf_follow "Checking if remote end is a Synology NAS..." "\e[1;32mYes\e[0m" "\e[1;31mNo\e[0m" is_remote_synology; then
IS_REMOTE_SYNOLGY=1
fi
if [ $IS_REMOTE_SYNOLGY -eq 1 ]; then
wrn "The remote end appears to be a Synology NAS."
wrn "Please make sure you have installed borg on the remote end."
wrn "To install borg on a Synology NAS you can use the Synology Package Center:"
wrn "- Open the Package Center"
wrn "- Go to Settings > Package Sources"
wrn "- Add a package source named 'Community' with the Location http://packages.synocommunity.com"
wrn "- Go to the Community section and search for 'Borg'"
wrn "- Install the 'Borg' package"
wrn ""
wrn "You also need to enable user homes in the Synology Control Panel:"
wrn "- Open the Control Panel"
wrn "- Go to User & Group > Advanced"
wrn "- At the bottom, check 'Enable user home service'"
wrn "- Apply the changes"
wrn ""
wrn "PLEASE DO NOT CONTINUE UNTIL YOU HAVE INSTALLED BORG ON THE REMOTE END."
wrn ""
wrnw "Press any key to continue..."
if ! inf_follow "Checking if remote end has borg installed..." "\e[1;32mYes\e[0m" "\e[1;31mNo\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" borg --version; then
if inf_follow "Checking if borg was installed at /usr/local/bin..." "\e[1;32mYes\e[0m" "\e[1;31mNo\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" test -f /usr/local/bin/borg; then
if inf_follow "Creating symlink to /bin/borg..." "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" ln -s /usr/local/bin/borg /bin/borg; then
inf "Successfully created symlink to /bin/borg."
else
err "Failed to create symlink to /bin/borg."
err "Please login to the remote end via ssh at $SSH_USER@$SSH_HOST and create the symlink manually."
err "The required command is: sudo ln -s /usr/local/bin/borg /bin/borg"
err "Please to not continue until you have created the symlink."
err ""
errw "Press any key to continue..."
fi
else
err "Borg could not be found on the remote end at /usr/local/bin (which is the default installation path for Synology NAS)."
err "Please make sure you have installed borg on the remote end."
exit 1
fi
fi
else
if wrnp "The remote end does not have borg installed. Do you want to install it now? [y/N]"; then if wrnp "The remote end does not have borg installed. Do you want to install it now? [y/N]"; then
if ! inf_follow "Updating package repositories on remote end" "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" apt-get update; then if ! inf_follow "Updating package repositories on remote end" "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command ssh -i "$SSH_KEY_FILE" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" apt-get update; then
err "Failed to update package repositories on remote end." err "Failed to update package repositories on remote end."
@ -641,6 +750,7 @@ if ! inf_follow "Checking if remote end has borg installed..." "\e[1;32mYes\e[0m
err "This is required in order to do backups using borgmatic." err "This is required in order to do backups using borgmatic."
exit 1 exit 1
fi fi
fi
fi fi
inf "Setting up borgmatic configuration..." inf "Setting up borgmatic configuration..."
@ -692,7 +802,16 @@ if ! inf_follow "Validating borgmatic configuration..." "\e[1;32mOK\e[0m" "\e[1;
exit 1 exit 1
fi fi
if [ "$BACKUP_ENCRYPTION" != "none" ]; then # ask for backup passphrase if none is set and encryption is enabled
if [ -z "$BACKUP_PASSPHRASE" ] && [ "$BACKUP_ENCRYPTION" != "none" ]; then
wrn "Please enter the passphrase for the backup encryption."
wrn "This is required to encrypt your backups."
read -s -p "Passphrase: " BACKUP_PASSPHRASE
echo ""
fi
if [ "$BACKUP_ENCRYPTION" == "none" ]; then
if ! inf_follow "Setting up borgmatic repository without encryption..." "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command /root/.local/pipx/venvs/borgmatic/bin/borgmatic init --make-parent-dirs --encryption=none; then if ! inf_follow "Setting up borgmatic repository without encryption..." "\e[1;32mOK\e[0m" "\e[1;31mFAILED\e[0m" run_command /root/.local/pipx/venvs/borgmatic/bin/borgmatic init --make-parent-dirs --encryption=none; then
err "Failed to set up borgmatic repository without encryption." err "Failed to set up borgmatic repository without encryption."
err "If the error persists, please contact the support at $SCRIPT_SUPPORT." err "If the error persists, please contact the support at $SCRIPT_SUPPORT."