187 lines
6.6 KiB
Bash
187 lines
6.6 KiB
Bash
#!/bin/bash
|
|
|
|
TITLE="Backup"
|
|
DESCRIPTION="Back up your home folder daily to your Nextcloud files"
|
|
|
|
CORE_CONF="$HOME/.config/coredesktop/core.conf"
|
|
BACKUP_CONF="$HOME/.config/coredesktop/backup.conf"
|
|
UNITS="$HOME/.config/systemd/user"
|
|
source "$COREDESKTOP/configure.d/lib/nextcloud.sh"
|
|
[ -f "$CORE_CONF" ] && source "$CORE_CONF"
|
|
|
|
is_installed() {
|
|
command -v restic > /dev/null && command -v rclone > /dev/null && command -v secret-tool > /dev/null
|
|
}
|
|
|
|
backups_on() {
|
|
source "$COREDESKTOP/system/backup-env.sh" > /dev/null || return 1
|
|
[ -n "$RESTIC_PASSWORD_COMMAND" ] && systemctl --user is-enabled -q coredesktop-backup.timer
|
|
}
|
|
|
|
# Done when backing up to the main Core
|
|
is_configured() {
|
|
backups_on && [ "$BACKUP_WEBDAV" = "https://nextcloud.$CORE_DOMAIN/remote.php/dav/files/${CORE_EMAIL%@*}" ]
|
|
}
|
|
|
|
save_secret() {
|
|
printf '%s' "$3" | secret-tool store --label "CoreDesktop backup $1 ($2)" \
|
|
coredesktop backup item "$1" url "$2"
|
|
}
|
|
|
|
# The backup gets its own app password, so revoking it stops only backups
|
|
nextcloud_login() {
|
|
local tries
|
|
[ -n "$(backup_secret nextcloud "$WEBDAV")" ] \
|
|
&& rclone lsf --max-depth 1 ":webdav:" > /dev/null 2>&1 && return 0
|
|
for tries in 1 2 3; do
|
|
read -rsp "Your Core password: " PASSWORD
|
|
echo
|
|
nextcloud_app_password "CoreDesktop backup on $HOSTNAME"
|
|
case $? in
|
|
0) break ;;
|
|
2) echo "Nextcloud says that password is wrong." ;;
|
|
*) echo "Couldn't reach Nextcloud at $NEXTCLOUD."; return 1 ;;
|
|
esac
|
|
done
|
|
unset PASSWORD
|
|
[ -n "$APP_PASSWORD" ] || return 1
|
|
save_secret nextcloud "$WEBDAV" "$APP_PASSWORD" || return 1
|
|
unset APP_PASSWORD
|
|
RCLONE_WEBDAV_PASS="$(backup_secret nextcloud "$WEBDAV" | rclone obscure -)"
|
|
}
|
|
|
|
new_passphrase() {
|
|
local pass
|
|
pass="$(head -c 24 /dev/urandom | base64)"
|
|
echo "Your backup is encrypted with this passphrase:"
|
|
echo
|
|
echo " $pass"
|
|
echo
|
|
echo "Save it somewhere other than this computer, such as Bitwarden. Without it, the"
|
|
echo "backup can't be read if this computer is lost. It's kept in your keyring so the"
|
|
echo "daily backup can run."
|
|
until confirm "Have you saved it?"; do :; done
|
|
save_secret passphrase "$WEBDAV/$BACKUP_DIR" "$pass"
|
|
}
|
|
|
|
# Stop the daily backup and any running now, and remove its units
|
|
stop_backups() {
|
|
systemctl --user disable --now coredesktop-backup.timer 2> /dev/null
|
|
systemctl --user stop coredesktop-backup.service 2> /dev/null
|
|
rm -f "$UNITS"/coredesktop-backup.{service,timer}
|
|
systemctl --user daemon-reload
|
|
}
|
|
|
|
# Delete the backup from Nextcloud, then what's on this computer for it:
|
|
# without the backup, the passphrase and app password are no use
|
|
delete_backups() {
|
|
local app_password
|
|
nextcloud_login || { echo "Couldn't sign in to Nextcloud."; return 1; }
|
|
echo "Deleting $BACKUP_DIR from your Nextcloud files..."
|
|
rclone purge ":webdav:$BACKUP_DIR" \
|
|
|| { echo "rclone couldn't delete $BACKUP_DIR."; return 1; }
|
|
echo "Deleted. Nextcloud keeps it in its trash bin, where it still uses space, until you empty it."
|
|
|
|
app_password="$(backup_secret nextcloud "$WEBDAV")"
|
|
[ -n "$app_password" ] && nextcloud_revoke_app_password "$app_password"
|
|
secret-tool clear coredesktop backup item nextcloud url "$WEBDAV"
|
|
secret-tool clear coredesktop backup item passphrase url "$WEBDAV/$BACKUP_DIR"
|
|
rm -f "$BACKUP_CONF"
|
|
}
|
|
|
|
turn_off() {
|
|
local answer
|
|
WEBDAV="$BACKUP_WEBDAV"
|
|
CORE_USER="$BACKUP_USER"
|
|
NEXTCLOUD="${BACKUP_WEBDAV%%/remote.php/*}"
|
|
|
|
stop_backups
|
|
echo "Backups are off."
|
|
|
|
echo
|
|
echo "The backups made so far are still in $BACKUP_DIR in your Nextcloud files."
|
|
if ! confirm "Delete them? They can't be restored from after that."; then
|
|
echo "Kept them. To turn backups back on: configure backup"
|
|
return 0
|
|
fi
|
|
read -rp "To delete them, type the folder name ($BACKUP_DIR): " answer
|
|
if [ "$answer" != "$BACKUP_DIR" ]; then
|
|
echo "That's not the folder name, so the backups were kept."
|
|
return 0
|
|
fi
|
|
delete_backups
|
|
}
|
|
|
|
run_configure() {
|
|
local pass choice
|
|
if backups_on &> /dev/null; then
|
|
if is_configured &> /dev/null; then
|
|
echo "Your home folder is backed up daily to $BACKUP_DIR in your Nextcloud files."
|
|
echo
|
|
echo " 1) Set it up again"
|
|
else
|
|
echo "Your home folder is backed up daily to $BACKUP_DIR on ${BACKUP_WEBDAV%%/remote.php/*},"
|
|
echo "which isn't your main Core."
|
|
echo
|
|
echo " 1) Back up to your main Core ($CORE_DOMAIN) instead; the backups so far stay where they are"
|
|
fi
|
|
echo " 2) Turn backups off"
|
|
echo " q) Leave it as it is"
|
|
echo
|
|
read -rp "Choose: " choice
|
|
case "$choice" in
|
|
1) ;;
|
|
2) turn_off; return ;;
|
|
*) return 0 ;;
|
|
esac
|
|
fi
|
|
|
|
if [ -z "$CORE_DOMAIN" ] || [ -z "$CORE_EMAIL" ]; then
|
|
echo "Backups go to your Nextcloud files, so set up your Core first: configure core"
|
|
return 1
|
|
fi
|
|
CORE_USER="${CORE_EMAIL%@*}"
|
|
NEXTCLOUD="https://nextcloud.$CORE_DOMAIN"
|
|
WEBDAV="$NEXTCLOUD/remote.php/dav/files/$CORE_USER"
|
|
BACKUP_DIR=".backup-$HOSTNAME"
|
|
|
|
mkdir -p "$(dirname "$BACKUP_CONF")"
|
|
{
|
|
printf 'BACKUP_WEBDAV=%q\n' "$WEBDAV"
|
|
printf 'BACKUP_USER=%q\n' "$CORE_USER"
|
|
printf 'BACKUP_DIR=%q\n' "$BACKUP_DIR"
|
|
} > "$BACKUP_CONF"
|
|
source "$COREDESKTOP/system/backup-env.sh"
|
|
|
|
nextcloud_login || { echo "Couldn't sign in to Nextcloud."; return 1; }
|
|
|
|
if rclone lsf --files-only ":webdav:$BACKUP_DIR" 2> /dev/null | grep -qx config; then
|
|
# Already there, e.g. after reinstalling: it needs the passphrase from then
|
|
if [ -z "$RESTIC_PASSWORD_COMMAND" ] || ! restic cat config &> /dev/null; then
|
|
echo "There's already a backup in $BACKUP_DIR in your Nextcloud files."
|
|
read -rsp "Its passphrase: " pass
|
|
echo
|
|
RESTIC_PASSWORD_COMMAND= RESTIC_PASSWORD="$pass" restic cat config > /dev/null \
|
|
|| { echo "restic couldn't open it with that passphrase."; return 1; }
|
|
save_secret passphrase "$WEBDAV/$BACKUP_DIR" "$pass" || return 1
|
|
fi
|
|
echo "Using the backup in $BACKUP_DIR."
|
|
else
|
|
new_passphrase || return 1
|
|
source "$COREDESKTOP/system/backup-env.sh"
|
|
echo "Creating the backup in $BACKUP_DIR in your Nextcloud files..."
|
|
restic init || return 1
|
|
fi
|
|
|
|
mkdir -p "$UNITS"
|
|
cp "$COREDESKTOP"/system/systemd/coredesktop-backup.{service,timer} "$UNITS/" || return 1
|
|
systemctl --user daemon-reload
|
|
systemctl --user enable --now coredesktop-backup.timer || return 1
|
|
echo "Your home folder will be backed up daily to $BACKUP_DIR in your Nextcloud files."
|
|
|
|
if confirm_yes "Start the first backup now? It runs in the background and can take hours."; then
|
|
systemctl --user start --no-block coredesktop-backup.service
|
|
echo "Started. To follow it: journalctl --user -fu coredesktop-backup"
|
|
fi
|
|
}
|