From 25bdcf053bf98359d1834942bcb0846a0b28a461 Mon Sep 17 00:00:00 2001 From: Josh Lay Date: Thu, 20 Jun 2024 16:11:32 -0500 Subject: [PATCH] backup_home: cover --- .../.config/autostart-i3ipc.yml | 3 +- outerheaven.init3.home/.local/bin/backup_home | 98 +++++++++++++++++++ update.sh | 3 + 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100755 outerheaven.init3.home/.local/bin/backup_home diff --git a/outerheaven.init3.home/.config/autostart-i3ipc.yml b/outerheaven.init3.home/.config/autostart-i3ipc.yml index 2018b1b..4fef089 100644 --- a/outerheaven.init3.home/.config/autostart-i3ipc.yml +++ b/outerheaven.init3.home/.config/autostart-i3ipc.yml @@ -2,7 +2,7 @@ autostarts: pre: # blocking tasks before others; ie: backup - "truncate -s 0 --no-create ~/.gnupg/trezor/gpg-agent.log" # this grows ridiculously large/fast, clear it on login - before backup - - "kitty ~/.local/bin/backup_restic --single-instance --instance-group autostart" + - "foot backup_home" # custom 'restic' and 'pass'-drive backup script in ~/.local/bin weekend: [] # blocking tasks to run on weekends, after 'pre' but before the rest in 'common'. 'work' is excluded from weekends. # - "/usr/bin/flatpak update --user --noninteractive --assumeyes | systemd-cat -t flatpak-update" common: @@ -21,6 +21,7 @@ autostarts: - "env XDG_CURRENT_DESKTOP=Unity tuned-switcher" - "thunderbird -P jlay" # 'thunderbird-wayland' has finally joined/flattened - also, I set the env var; MOZ_ENABLE_WAYLAND=1 - "flatpak run --file-forwarding org.signal.Signal --class='Signal' --app-id='Signal'" + - "virt-manager" # - "flatpak run org.kde.kweather" # - "flatpak run com.belmoussaoui.Authenticator" # - "bash -c 'ulimit -n 1048576; strawberry --quiet'" diff --git a/outerheaven.init3.home/.local/bin/backup_home b/outerheaven.init3.home/.local/bin/backup_home new file mode 100755 index 0000000..7e50cfb --- /dev/null +++ b/outerheaven.init3.home/.local/bin/backup_home @@ -0,0 +1,98 @@ +#!/bin/bash +# +# backs up home using restic and encryption +# passphrases protected by GPG/Trezor hardware wallet + +function do_backup() { + RUN_TIME="$(date +'%H:%M on %Y-%m-%d')" + echo "Starting on-login backup at ${RUN_TIME}" + echo "" + restic -r "${BACKUP_DEST}" backup \ + --compression "${COMPRESSION}" \ + --exclude-file="${EXCLUDES_FILE}" \ + --one-file-system \ + "${BACKUP_SOURCE}" + return $? +} + +function read_enter() { + # used in cases where we require input before continuing/exiting + # ... but don't care what the input is + echo "Please press Enter to exit..." + read -r +} + +set -x -o nounset -o pipefail +# start vars, what to backup/exclude and where to log +EXCLUDES_FILE="${HOME}/.restic_excludes" +BACKUP_SOURCE="${HOME}" + +# misc options; compression / exit delay / retention period +COMPRESSION="${COMPRESSION:-auto}" # default auto, one of [auto, off, max] +EXIT_DELAY="${EXIT_DELAY:-3}" +KEEP="${KEEP:-7d}" + +# define where to write backups - one at a time +# double slashes for remote volumes are significant to separate host from path +BACKUP_DEST="${BACKUP_DEST:-/raid1-evos/backups/restic}" +PASS_NAME="${PASS_NAME:-restic/raid1-evos}" +# PASS_NAME provides the path to the 'pass' object with the repo password +# ie: 'pass restic/t7usb' would show the password; provided/backed by Trezor wallet through GPG +# alts: +# BACKUP_DEST="/mnt/t7usb/restic" +# PASS_NAME="restic/t7usb" +# BACKUP_DEST="sftp://zeta.jlay.dev//backup/restic" # uses SATA zvol +# PASS_NAME="restic/zeta" + +# set restic specific vars; performance but also auth +export RESTIC_READ_CONCURRENCY=8 # default 2 +export RESTIC_PACK_SIZE=32 # default 16 MiB +export RESTIC_PROGRESS_FPS=1 +# export RESTIC_PASSWORD_FILE="/rust/backups/workstation/.restic_password_to_zeta_podvol" +# redundant copy at /raid1-evos/backups/.workstation_restic_password_to_zeta_podvol +set +x + +# ensure Trezor GPG agent is available/used for 'pass' +export GNUPGHOME="${HOME}/.gnupg/trezor" + +echo "Getting repository password with 'pass'/GPG; check hardware wallet for verification" +RESTIC_PASSWORD=$(pass "${PASS_NAME}") +export RESTIC_PASSWORD +# declare and assign separately to avoid masking rc +# https://www.shellcheck.net/wiki/SC2155 + +# Check repository availability/consistency +restic check -r "$BACKUP_DEST" --no-lock --quiet +RESTIC_RC_CHECK=$? + +if (( RESTIC_RC_CHECK == 0 )); then + # happy path - check of the destination passed, continue w/ backup + echo -e "\nRestic repository is available and passed checks, proceeding" + echo -e "\nCleaning up caches" + restic cache --cleanup + echo -e "\nCleaning backups older than $KEEP" + restic -r "$BACKUP_DEST" forget --prune --keep-within "$KEEP" --quiet + if do_backup; then + echo -e "\nBackup succeeded!" + else + echo -e "\nBackup failed!" + # require input before continuing/exiting + read_enter + fi +else + # empty line to separate our summary from the noise + echo "" + # unhappy path - check of the destination restic repo failed, and we didn't backup + if (( RESTIC_RC_CHECK == 3 )); then + echo "The repo doesn't seem to exist - cannot backup. Is '$BACKUP_DEST' mounted/available?" + else + echo "An unknown error occurred in checking '$BACKUP_DEST'." + echo "Review output, no assurances on consistency with any backups. Storage medium failures possible." + fi + # require input before continuing/exiting + read_enter +fi +echo "Exiting in $EXIT_DELAY seconds" +sleep "${EXIT_DELAY}" + +unset RESTIC_PASSWORD diff --git a/update.sh b/update.sh index f076fce..bb64bb6 100755 --- a/update.sh +++ b/update.sh @@ -20,6 +20,9 @@ DOTS=( '.config/nvim/coc-settings.json' '.config/autostart-i3ipc.yml' '.config/sway/' + '.config/swayidle/config' + '.config/swaylock/config' + '.local/bin/backup_home' '.local/bin/note-taker.sh' # run by Kitty in a 'triplesplit' session, one of many of autostart 'wants' in '...-i3ipc.yml' above )