#!/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" [ -f "$CORE_CONF" ] && source "$CORE_CONF" [ -f "$BACKUP_CONF" ] && source "$BACKUP_CONF" is_installed() { command -v borg > /dev/null && command -v secret-tool > /dev/null } # The passphrase is in the keyring under the repository's path, so the # backup can run without asking passphrase() { secret-tool lookup coredesktop backup repo "$1" } is_configured() { [ -n "$BORG_REPO" ] && [ -n "$(passphrase "$BORG_REPO")" ] \ && systemctl --user is-enabled -q coredesktop-backup.timer } # system/backup uses borg 1.2 to 1.4; borg 2 changed its commands borg_supported() { local version version="$(borg --version | awk '{print $2}')" [[ "$version" =~ ^1\.([2-9]|[1-9][0-9])\. ]] && return 0 echo "This needs borg 1.2 to 1.4, and borg $version is installed." return 1 } save_passphrase() { printf '%s' "$2" | secret-tool store --label "CoreDesktop backup ($1)" coredesktop backup repo "$1" } run_configure() { local mount="/mnt/$CORE_DOMAIN" repo pass borg_supported || return 1 if [ -z "$CORE_DOMAIN" ] || ! mountpoint -q "$mount"; then echo "Backups go to your Nextcloud files, so set those up first (configure core), and check they're mounted." return 1 fi repo="$mount/.backup-$HOSTNAME" if [ -f "$repo/config" ]; then # Already there, e.g. after reinstalling: it needs the passphrase from then pass="$(passphrase "$repo")" if [ -z "$pass" ] || ! BORG_PASSPHRASE="$pass" borg info "$repo" &> /dev/null; then echo "There's already a backup at $repo." read -rsp "Its passphrase: " pass echo BORG_PASSPHRASE="$pass" borg info "$repo" > /dev/null || { echo "borg couldn't open it with that passphrase."; return 1; } save_passphrase "$repo" "$pass" || return 1 fi echo "Using the backup at $repo." else 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_passphrase "$repo" "$pass" || return 1 echo "Creating the backup at $repo..." BORG_PASSPHRASE="$pass" borg init --encryption=repokey-blake2 "$repo" || return 1 # davfs2 copies each file to a local cache before uploading it, and some # servers refuse large uploads, so keep borg's files to 50 MB, not 500 BORG_PASSPHRASE="$pass" borg config "$repo" max_segment_size 52428800 || return 1 fi mkdir -p "$(dirname "$BACKUP_CONF")" { printf 'BORG_REPO=%q\n' "$repo" printf 'BACKUP_MOUNT=%q\n' "$mount" } > "$BACKUP_CONF" 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 $repo." 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 }