#!/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 } is_configured() { source "$COREDESKTOP/system/backup-env.sh" > /dev/null || return 1 [ -n "$RESTIC_PASSWORD_COMMAND" ] && systemctl --user is-enabled -q coredesktop-backup.timer } 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" } run_configure() { local pass 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 }