borg-backup-scripts/init.sh

152 lines
4.2 KiB
Bash
Executable file

#!/bin/bash
SELF="$0"
HOST=""
PORT="22"
REMOTE_PATH=""
NAME=""
LOGIN="$(whoami)"
die() {
echo -e $1 | sed -e 's-^-! -' >&2
exit 1
}
usage() {
echo -e "usage: $SELF PROFILE_NAME --host=server --port=22 --login=backup-user --directory=/backup/path" >&2
exit 1
}
generate_passphrase() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 64
}
init_config_dir() {
[ "x$HOST" == "x" ] && usage
install --directory --owner=$(id -u) --group=$(id -g) --mode=600 "$CONFIGDIR" || die "Can't create directory $CONFIGDIR"
umask 177
generate_passphrase > "$CONFIGDIR/borg_passphrase"
ssh-keygen -t ed25519 -N "" -q -f "$CONFIGDIR/ssh_key" -C "borg access from $(hostname --long)"
ssh-copy-id -i "$CONFIGDIR/ssh_key.pub" -p $PORT "$LOGIN@$HOST"
}
set_env_config() {
local file="$1"
local param="$2"
local value="$3"
# test current config
# file does not exist
[ ! -e $file ] && echo "$param=$value" >> $file
# file isn't readable
[ ! -r $file ] && die "Config file isn't readable: $file"
# file exists and value is set => early exit
local curr_line="$(grep "^$param=" $file)"
if [ "x$curr_line" == "x" ]; then
# file ist nicht änderbar
[ ! -w $file ] && die "Config file isn't writable: $file"
# param isn't set => append
echo "$param=$value" >> $file
elif [ "x${curr_line#$param=}" != "x$value" ]; then
# param is set with different value
die "Environment parameter '$param' is already set to '${curr_line#$param=}' in config file: $file\nPlease confirm that you know what you're doing by manually setting the parameter to the desired value '$value'."
fi
return 0
}
test_ssh() {
ssh -q -o "BatchMode=yes" -i "$CONFIGDIR/ssh_key" -p "$PORT" "$LOGIN@$HOST" "mkdir -p $REMOTE_PATH" \
|| die "SSH connection attempt failed."
return 0
}
test_repo_exists() {
ssh -q -o "BatchMode=yes" -i "$CONFIGDIR/ssh_key" -p "$PORT" "$LOGIN@$HOST" "cat $REMOTE_PATH/README" 2>/dev/null | grep -q "This is a Borg Backup repository."
return $?
}
invoke_borg() {
# do some sandboxinng
systemd-run --quiet --collect --unit=temp-borg-init-sandbox.service \
--pipe < /etc/borg/$NAME/borg_passphrase \
--working-directory=/tmp \
-p "ConfigurationDirectory=borg/$NAME" \
-p "CacheDirectory=borg/$NAME" \
-p "ConfigurationDirectoryMode=750" \
-p "CacheDirectoryMode=750" \
-p "PrivateTmp=yes" \
-p "ReadOnlyDirectories=/" \
-p "EnvironmentFile=/etc/borg/$NAME/config.env" \
--setenv=BORG_PASSPHRASE_FD=0 \
--setenv=BORG_BASE_DIR=/tmp/ \
--setenv=BORG_CONFIG_DIR=/etc/borg/$NAME \
--setenv=BORG_CACHE_DIR=/var/cache/borg/$NAME \
/usr/bin/borg $@
}
init_repo() {
echo "> init repo"
invoke_borg init -e repokey-blake2 || die "failed to init borg repo"
}
show_repo() {
echo "> testing repo connection"
invoke_borg info || die "failed to access borg repo"
}
for arg in "$@"; do
case "$arg" in
-h*)
HOST="${arg#-h}"
;;
--host=*)
HOST="${arg#--host=}"
;;
-p*)
PORT="${arg#-p}"
;;
--port=*)
PORT="${arg#--port=}"
;;
-l*)
LOGIN="${arg#-l}"
;;
--login=*)
LOGIN="${arg#--login=}"
;;
-d*)
REMOTE_PATH="${arg#-d}"
;;
--directory=*)
REMOTE_PATH="${arg#--directory=}"
;;
-*)
usage
;;
*)
[ "x$NAME" == "x" ] || usage
NAME="$arg"
;;
esac
done
[ "x$NAME" == "x" ] && usage
[ "x$REMOTE_PATH" == "x" ] && usage
CONFIGDIR="/etc/borg/$NAME"
echo "> checking config"
[ -e "$CONFIGDIR" ] || init_config_dir || die "Failed setting up config directory and ssh connection"
[ -d "$CONFIGDIR" ] || die "Config directory isn't valid: $CONFIGDIR"
[ -r "$CONFIGDIR/borg_passphrase" ] || die "File isn't readable: $CONFIGDIR/borg_passphrase"
[ -r "$CONFIGDIR/ssh_key" ] || die "File isn't readable: $CONFIGDIR/ssh_key"
# write config every time, parameter may change with each invocation
set_env_config "$CONFIGDIR/config.env" BORG_REPO "ssh://$LOGIN@$HOST:${PORT}${REMOTE_PATH}"
set_env_config "$CONFIGDIR/config.env" BORG_RSH "ssh -i $CONFIGDIR/ssh_key"
[ -r "$CONFIGDIR/config.env" ] || die "File isn't readable: $CONFIGDIR/config.env"
echo "> testing ssh and destination path"
test_ssh || die "Can't establish ssh connection! Try: ssh-copy-id -i $CONFIGDIR/ssh_key.pub -p $PORT $LOGIN@$HOST"
echo "> testing borg repo"
test_repo_exists || init_repo
show_repo