initial-setup: clean up, add PORT option, improve --update
This commit is contained in:
parent
b16c4d7330
commit
988fe5db3f
1
.gitea/README.md
Symbolic link
1
.gitea/README.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../templates/README.md
|
198
initial-setup.sh
198
initial-setup.sh
|
@ -1,11 +1,26 @@
|
|||
|
||||
#!/bin/bash
|
||||
|
||||
# These can be overridden when running this script
|
||||
HOSTNAME=${HOSTNAME:-$(hostname)}
|
||||
BACKUP_HOST=${BACKUP_HOST:-backup.jim.sh}
|
||||
BACKUP_USER=${BACKUP_USER:-jim-backups}
|
||||
BACKUP_REPO=${BACKUP_REPO:-borg/${HOSTNAME}}
|
||||
set_default_variables()
|
||||
{
|
||||
HOSTNAME=${HOSTNAME:-$(hostname)}
|
||||
BACKUP_HOST=${BACKUP_HOST:-backup.jim.sh}
|
||||
BACKUP_PORT=${BACKUP_PORT:-222}
|
||||
BACKUP_USER=${BACKUP_USER:-jim-backups}
|
||||
BACKUP_REPO=${BACKUP_REPO:-borg/${HOSTNAME}}
|
||||
|
||||
# Use stable host ID in case MAC address changes.
|
||||
# Note that this host ID is only used to manage locks, so it's
|
||||
# not crucial that it remains stable.
|
||||
UUID=$(python3 -c 'import uuid;print(uuid.getnode())')
|
||||
HOSTID=${BORG_HOST_ID:-"${HOSTNAME}@${UUID}"}
|
||||
|
||||
log "Configuration:"
|
||||
log " Backup server user: ${BACKUP_USER}"
|
||||
log " Backup server host: ${BACKUP_HOST}"
|
||||
log " Backup server port: ${BACKUP_PORT}"
|
||||
log " Repository path: ${BACKUP_REPO}"
|
||||
}
|
||||
|
||||
# Main dir is where this repo was checked out
|
||||
BORG_DIR="$(realpath "$(dirname "$0")")"
|
||||
|
@ -13,11 +28,6 @@ cd "${BORG_DIR}"
|
|||
|
||||
BORG_BIN="${BORG_DIR}/bin/borg.$(uname -m)"
|
||||
|
||||
# Use stable host ID in case MAC address changes.
|
||||
# Note that this host ID is only used to manage locks, so it's
|
||||
# not crucial that it remains stable.
|
||||
HOSTID="${HOSTNAME}@$(python3 -c 'import uuid;print(uuid.getnode())')"
|
||||
|
||||
function error_handler() {
|
||||
echo "Error at $1 line $2:"
|
||||
echo -n '>>> ' ; tail -n +"$2" < "$1" | head -1
|
||||
|
@ -45,13 +55,14 @@ create_borg_vars()
|
|||
VARS=${BORG_DIR}/vars.sh
|
||||
|
||||
# These variables are used elsewhere in this script
|
||||
BORG_REPO="ssh://${BACKUP_USER}@${BACKUP_HOST}/./${BACKUP_REPO}"
|
||||
BORG_REPO="ssh://${BACKUP_USER}@${BACKUP_HOST}:${BACKUP_PORT}/./${BACKUP_REPO}"
|
||||
BORG=${BORG_DIR}/borg.sh
|
||||
SSH=$BORG_DIR/ssh
|
||||
|
||||
cat >"$VARS" <<EOF
|
||||
export BACKUP_USER=${BACKUP_USER}
|
||||
export BACKUP_HOST=${BACKUP_HOST}
|
||||
export BACKUP_PORT=$(BACKUP_PORT}
|
||||
export BACKUP_REPO=${BACKUP_REPO}
|
||||
export HOSTNAME=${HOSTNAME}
|
||||
export BORG_REPO=${BORG_REPO}
|
||||
|
@ -67,50 +78,59 @@ EOF
|
|||
fi
|
||||
}
|
||||
|
||||
# Update paths in README and backup.py
|
||||
# Copy templated files, filling in templates as needed
|
||||
install_templated_files()
|
||||
{
|
||||
for i in README.md notify.sh; do
|
||||
sed -e "s!\${HOSTNAME}!${HOSTNAME}!g" \
|
||||
-e "s!\${BORG_DIR}!${BORG_DIR}!g" \
|
||||
-e "s!\${BORG_BIN}!${BORG_BIN}!g" \
|
||||
-e "s!\${BACKUP_USER}!${BACKUP_USER}!g" \
|
||||
-e "s!\${BACKUP_HOST}!${BACKUP_HOST}!g" \
|
||||
-e "s!\${BACKUP_REPO}!${BACKUP_REPO}!g" \
|
||||
templates/$i > $i
|
||||
done
|
||||
}
|
||||
|
||||
# Update local paths in scripts
|
||||
update_paths()
|
||||
{
|
||||
sed -i \
|
||||
-e "s!\${HOSTNAME}!${HOSTNAME}!g" \
|
||||
-e "s!\${BORG_DIR}!${BORG_DIR}!g" \
|
||||
-e "s!\${BORG_BIN}!${BORG_BIN}!g" \
|
||||
-e "s!\${BACKUP_USER}!${BACKUP_USER}!g" \
|
||||
-e "s!\${BACKUP_HOST}!${BACKUP_HOST}!g" \
|
||||
-e "s!\${BACKUP_REPO}!${BACKUP_REPO}!g" \
|
||||
README.md
|
||||
|
||||
sed -i\
|
||||
-e "1c#!${BORG_DIR}/.venv/bin/python" \
|
||||
backup.py
|
||||
}
|
||||
|
||||
# See if we're just supposed to update an existing install, or recovering
|
||||
RECOVER=0
|
||||
if [ "$1" == "--recover" ] ; then
|
||||
if [ -e "vars.sh" ]; then
|
||||
echo "It looks like this borg was already set up, can only recover from fresh start"
|
||||
parse_args()
|
||||
{
|
||||
RECOVER=0
|
||||
UPDATE=0
|
||||
if [ "$1" == "--recover" ] ; then
|
||||
if [ -e "vars.sh" ]; then
|
||||
echo "It looks like this borg was already set up, can only recover from fresh start"
|
||||
exit 1
|
||||
fi
|
||||
RECOVER=1
|
||||
|
||||
elif [ "$1" == "--update-paths" ] || [ "$1" == "--update" ] ; then
|
||||
if [ ! -e "vars.sh" ]; then
|
||||
echo "Can't update, not set up yet"
|
||||
exit 1
|
||||
fi
|
||||
UPDATE=1
|
||||
|
||||
elif [ -n "$1" ] ; then
|
||||
echo "Unknown arg $1"
|
||||
exit 1
|
||||
fi
|
||||
RECOVER=1
|
||||
|
||||
elif [ "$1" == "--update-paths" ] || [ "$1" == "--update" ] ; then
|
||||
if [ -e "vars.sh" ]; then
|
||||
echo "Updating paths and variables"
|
||||
update_paths
|
||||
setup_venv
|
||||
create_borg_vars
|
||||
exit 0
|
||||
else
|
||||
echo "Can't update, not set up yet"
|
||||
elif [ -e "vars.sh" ]; then
|
||||
echo "Error: BORG_DIR $BORG_DIR already looks set up; giving up."
|
||||
echo "Use \"git clean\" to return it to original state if desired".
|
||||
echo "Or specify --update to refresh things from latest git."
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
elif [ -e "vars.sh" ]; then
|
||||
echo "Error: BORG_DIR $BORG_DIR already looks set up; giving up."
|
||||
echo "Use \"git clean\" to return it to original state if desired"
|
||||
exit 1
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
# Make a temp dir to work in
|
||||
TMP=$(mktemp -d)
|
||||
|
@ -207,11 +227,12 @@ EOF
|
|||
ssh -F "$SSH/config" -o BatchMode=no -o PubkeyAuthentication=no \
|
||||
-o ControlMaster=yes -o ControlPath="$TMP/ssh-control" \
|
||||
-o StrictHostKeyChecking=accept-new \
|
||||
-p "${BACKUP_PORT}" \
|
||||
-f "${BACKUP_USER}@${BACKUP_HOST}" sleep 600
|
||||
if ! run_ssh_command true >/dev/null 2>&1 </dev/null ; then
|
||||
error "SSH failed"
|
||||
fi
|
||||
log "Connected to ${BACKUP_USER}@${BACKUP_HOST}"
|
||||
log "Connected to ${BACKUP_USER}@${BACKUP_HOST}:${BACKUP_PORT}"
|
||||
|
||||
# Since we now have an SSH connection, check repo existence
|
||||
if [ $RECOVER -eq 0 ] && run_ssh_command "test -e $BACKUP_REPO"; then
|
||||
|
@ -239,7 +260,8 @@ EOF
|
|||
# Test that everything worked
|
||||
log "Testing SSH login with new key"
|
||||
if ! ssh -F "$SSH/config" -i "$SSH/id_ecdsa_appendonly" -T \
|
||||
"${BACKUP_USER}@${BACKUP_HOST}" "$REMOTE_BORG" --version </dev/null ; then
|
||||
-p "${BACKUP_PORT}" "${BACKUP_USER}@${BACKUP_HOST}" "$REMOTE_BORG" \
|
||||
--version </dev/null ; then
|
||||
error "Logging in with a key failed -- is server set up correctly?"
|
||||
fi
|
||||
log "Remote connection OK!"
|
||||
|
@ -358,41 +380,59 @@ git_setup()
|
|||
git commit -a -m "autocommit after initial setup on ${HOSTNAME}"
|
||||
}
|
||||
|
||||
log "Configuration:"
|
||||
log " Backup server host: ${BACKUP_HOST}"
|
||||
log " Backup server user: ${BACKUP_USER}"
|
||||
log " Repository path: ${BACKUP_REPO}"
|
||||
main() {
|
||||
if [ $UPDATE -eq 1 ] ; then
|
||||
notice "Non-destructively updating paths, variables, and venv..."
|
||||
source vars.sh
|
||||
set_default_variables
|
||||
install_templated_files
|
||||
update_paths
|
||||
setup_venv
|
||||
create_borg_vars
|
||||
|
||||
setup_venv
|
||||
create_borg_vars
|
||||
generate_keys
|
||||
configure_ssh
|
||||
[ $RECOVER -eq 0 ] && create_repo
|
||||
export_keys
|
||||
configure_systemd
|
||||
update_paths
|
||||
git_setup
|
||||
notice "Testing borg: if host location changed, say 'y' here"
|
||||
${BORG_DIR}/borg.sh info
|
||||
|
||||
echo
|
||||
if [ $RECOVER -eq 1 ] ; then
|
||||
notice "You should be set up with borg pointing to the existing repo now."
|
||||
notice "Use commands like these to look at the backup:"
|
||||
notice " sudo /opt/borg/borg.sh info"
|
||||
notice " sudo /opt/borg/borg.sh list"
|
||||
notice "You'll want to now restore files like ${BORG_DIR}/config.yaml before enabling systemd timers"
|
||||
else
|
||||
notice "Add this password to Bitwarden:"
|
||||
notice ""
|
||||
notice " Name: borg ${HOSTNAME}"
|
||||
notice " Username: repo key"
|
||||
notice " Password: $PASS_REPOKEY"
|
||||
notice ""
|
||||
notice "Test the backup file list with"
|
||||
notice " sudo ${BORG_DIR}/backup.py --dry-run"
|
||||
notice "and make any necessary adjustments to:"
|
||||
notice " ${BORG_DIR}/config.yaml"
|
||||
fi
|
||||
notice "Done -- check 'git diff' and verify changes."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
set_default_variables
|
||||
setup_venv
|
||||
create_borg_vars
|
||||
generate_keys
|
||||
configure_ssh
|
||||
[ $RECOVER -eq 0 ] && create_repo
|
||||
export_keys
|
||||
configure_systemd
|
||||
install_templated_files
|
||||
update_paths
|
||||
git_setup
|
||||
|
||||
echo "All done"
|
||||
echo
|
||||
if [ $RECOVER -eq 1 ] ; then
|
||||
notice "You should be set up with borg pointing to the existing repo now."
|
||||
notice "Use commands like these to look at the backup:"
|
||||
notice " sudo ${BORG_DIR}/borg.sh info"
|
||||
notice " sudo ${BORG_DIR}/borg.sh list"
|
||||
notice "You'll want to now restore files like ${BORG_DIR}/config.yaml before enabling systemd timers"
|
||||
else
|
||||
notice "Add this password to Bitwarden:"
|
||||
notice ""
|
||||
notice " Name: borg ${HOSTNAME}"
|
||||
notice " Username: repo key"
|
||||
notice " Password: $PASS_REPOKEY"
|
||||
notice ""
|
||||
notice "Test the backup file list with"
|
||||
notice " sudo ${BORG_DIR}/backup.py --dry-run"
|
||||
notice "and make any necessary adjustments to:"
|
||||
notice " ${BORG_DIR}/config.yaml"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
echo "All done"
|
||||
}
|
||||
|
||||
parse_args "$@"
|
||||
main
|
||||
|
|
|
@ -13,14 +13,14 @@ Customize `/opt/borg/config.yaml` as desired.
|
|||
Cheat sheet
|
||||
===========
|
||||
|
||||
*After setup, the copy of this file on the client will have the
|
||||
variables in this section filled in automatically*
|
||||
*After setup, /opt/borg/README.md will have the variables in this
|
||||
section filled in automatically*
|
||||
|
||||
## Configuration
|
||||
|
||||
Hostname: ${HOSTNAME}
|
||||
Base directory: ${BORG_DIR}
|
||||
Destination: ${BACKUP_USER}@${BACKUP_HOST}
|
||||
Destination: ${BACKUP_USER}@${BACKUP_HOST}:${BACKUP_PORT}
|
||||
Repository: ${BACKUP_REPO}
|
||||
|
||||
## Commands
|
||||
|
@ -29,11 +29,11 @@ See when next backup is scheduled:
|
|||
|
||||
systemctl list-timers borg-backup.timer
|
||||
|
||||
See status of most recent backup:
|
||||
See status of most recent backup attempt:
|
||||
|
||||
systemctl status --full --lines 999999 --no-pager --all borg-backup
|
||||
journalctl --unit borg-backup --since "$(systemctl show -P ExecMainStartTimestamp borg-backup)"
|
||||
|
||||
Watch log:
|
||||
Watch live log:
|
||||
|
||||
journalctl --all --follow --unit borg-backup
|
||||
|
||||
|
@ -71,13 +71,13 @@ compromised, then you can run compaction manually directly on the
|
|||
backup host by logging in via SSH (bitwarden `ssh ${BACKUP_HOST} /
|
||||
${BACKUP_USER}`) and compacting there:
|
||||
|
||||
ssh ${BACKUP_USER}@${BACKUP_HOST} borg/borg compact --verbose --progress ${BACKUP_REPO}
|
||||
ssh -p ${BACKUP_PORT} ${BACKUP_USER}@${BACKUP_HOST} borg/borg compact --verbose --progress ${BACKUP_REPO}
|
||||
|
||||
This doesn't require the repo key. That key shouldn't be entered on
|
||||
the untrusted backup host, so for operations that need it, use a
|
||||
trusted host and run borg remotely instead, e.g.:
|
||||
|
||||
${BORG_BIN} --remote-path borg/borg info ${BACKUP_USER}@${BACKUP_HOST}:borg/${HOSTNAME}
|
||||
${BORG_BIN} --remote-path borg/borg info ssh://${BACKUP_USER}@${BACKUP_HOST}:${BACKUP_PORT}/borg/${HOSTNAME}
|
||||
|
||||
The repo passphrase is in bitwarden `borg ${HOSTNAME} / repo key`.
|
||||
|
||||
|
@ -139,5 +139,4 @@ Then run `borg.x86_64`. Confirm the version with `borg.armv7l --version`.
|
|||
|
||||
*Note:* This uses the deprecated `llfuse` instead of the newer `pyfuse3`.
|
||||
`pyfuse3` doesn't work because, at minimum, it pulls in `trio` which
|
||||
requires `ssl` which is explicitly excluded by
|
||||
`scripts/borg.exe.spec`.
|
||||
requires `ssl` which is explicitly excluded by `scripts/borg.exe.spec`.
|
|
@ -22,5 +22,6 @@ EMAIL="$2"
|
|||
ssh \
|
||||
-F "$SSH/config" \
|
||||
-i "$SSH/id_ecdsa_notify" \
|
||||
-p "$BACKUP_PORT" \
|
||||
"$BACKUP_USER@$BACKUP_HOST" \
|
||||
borg/notify.sh "$EMAIL"
|
Loading…
Reference in New Issue
Block a user