fix backup

This commit is contained in:
2026-10-26 16:21:27 -06:00
parent 8c8c59d6d5
commit 488b085713
7 changed files with 180 additions and 115 deletions
+20 -27
View File
@@ -1,18 +1,19 @@
#!/bin/bash
#
# Purpose : Back up your home folder with borg to your Nextcloud files, in
# /mnt/<domain>/.backup-<hostname>. Run daily by
# coredesktop-backup.timer; `configure backup` sets it up.
# Purpose : Back up your home folder with restic to your Nextcloud files, in
# .backup-<hostname>. Run daily by coredesktop-backup.timer;
# `configure backup` sets it up.
#
# Keeps 7 daily, 4 weekly and 6 monthly backups. To leave out more, list
# paths or borg patterns in ~/.config/coredesktop/backup-exclude, one per line.
# paths or patterns in ~/.config/coredesktop/backup-exclude, one per line.
# Wrapped in { ...; exit; } so bash reads the whole script up front; update
# replaces this file (git pull) while a backup may be running.
{
BACKUP_CONF="$HOME/.config/coredesktop/backup.conf"
COREDESKTOP="$HOME/.local/share/coredesktop"
USER_EXCLUDE="$HOME/.config/coredesktop/backup-exclude"
LOG_HINT="See: journalctl --user -u coredesktop-backup"
# Tell the desktop when a backup fails, as no one watches the timer
fail() {
@@ -21,22 +22,17 @@ fail() {
exit 1
}
[ -f "$BACKUP_CONF" ] || fail "Backups aren't set up. Run: configure backup"
source "$BACKUP_CONF"
source "$COREDESKTOP/system/backup-env.sh" || exit 1
[ -n "$RESTIC_REPOSITORY" ] || fail "Backups aren't set up. Run: configure backup"
[ -n "$RESTIC_PASSWORD_COMMAND" ] || fail "The backup's passphrase isn't in your keyring. Run: configure backup"
# The files mount comes up at login, perhaps before the network; give it a
# few minutes rather than writing into the empty folder underneath
# Run at login, perhaps before the network is up; give it a few minutes
for try in {1..10}; do
mountpoint -q "$BACKUP_MOUNT" && break
mount "$BACKUP_MOUNT" 2> /dev/null && break
curl -sf --max-time 10 -o /dev/null "${BACKUP_WEBDAV%%/remote.php/*}/status.php" && break
sleep 30
done
mountpoint -q "$BACKUP_MOUNT" || fail "Your Nextcloud files aren't mounted at $BACKUP_MOUNT."
export BORG_REPO
export BORG_PASSCOMMAND="secret-tool lookup coredesktop backup repo $BORG_REPO"
# Rebuilt by borg, or by reinstalling, so not worth the space
# Rebuilt by restic, or by reinstalling, so not worth the space
excludes=(
"$HOME/.cache"
"$HOME/.davfs2/cache"
@@ -52,23 +48,20 @@ excludes=(
)
exclude_args=(--exclude-caches)
for path in "${excludes[@]}"; do
exclude_args+=(--exclude "sh:$path")
exclude_args+=(--exclude "$path")
done
[ -f "$USER_EXCLUDE" ] && exclude_args+=(--exclude-from "$USER_EXCLUDE")
[ -f "$USER_EXCLUDE" ] && exclude_args+=(--exclude-file "$USER_EXCLUDE")
echo "Backing up $HOME to $BORG_REPO..."
echo "Backing up $HOME to $BACKUP_DIR in your Nextcloud files..."
# --one-file-system leaves out other mounts and btrfs subvolumes inside home
borg create --one-file-system --compression zstd --stats \
"${exclude_args[@]}" "::{hostname}-{now:%Y-%m-%dT%H:%M}" "$HOME"
restic backup --one-file-system --host "$HOSTNAME" "${exclude_args[@]}" "$HOME"
status=$?
# 1 is a warning, e.g. a file changed while it was read; the backup still exists
(( status <= 1 )) || fail "borg couldn't back up $HOME (exit $status). See: journalctl --user -u coredesktop-backup"
# 3 means some files couldn't be read; the rest were backed up
(( status == 0 || status == 3 )) || fail "restic couldn't back up $HOME (exit $status). $LOG_HINT"
echo "Removing old backups..."
borg prune --glob-archives '{hostname}-*' \
--keep-daily 7 --keep-weekly 4 --keep-monthly 6 \
|| fail "borg couldn't remove old backups. See: journalctl --user -u coredesktop-backup"
borg compact || fail "borg couldn't free space from old backups. See: journalctl --user -u coredesktop-backup"
restic forget --host "$HOSTNAME" --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune \
|| fail "restic couldn't remove old backups. $LOG_HINT"
echo "Backup finished."
exit 0
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
#
# Purpose : Point restic at your backup in your Nextcloud files. Sourced by
# system/backup and configure.d/20-backup.sh, and by you to look at
# or restore from a backup:
#
# source ~/.local/share/coredesktop/system/backup-env.sh
# restic snapshots
#
# To use another computer's backup, name its folder:
#
# source ~/.local/share/coredesktop/system/backup-env.sh .backup-<name>
#
# restic reaches Nextcloud over WebDAV through rclone, not the davfs2 mount,
# which can't safely replace files. The Nextcloud app password and the
# backup's passphrase are kept in your keyring.
BACKUP_CONF="$HOME/.config/coredesktop/backup.conf"
# A secret from the keyring: nextcloud (app password) or passphrase
backup_secret() {
secret-tool lookup coredesktop backup item "$1" url "$2"
}
if [ -f "$BACKUP_CONF" ]; then
source "$BACKUP_CONF"
BACKUP_DIR="${1:-$BACKUP_DIR}"
export RCLONE_WEBDAV_URL="$BACKUP_WEBDAV"
export RCLONE_WEBDAV_VENDOR=nextcloud
export RCLONE_WEBDAV_USER="$BACKUP_USER"
RCLONE_WEBDAV_PASS="$(backup_secret nextcloud "$BACKUP_WEBDAV" | rclone obscure -)"
export RCLONE_WEBDAV_PASS
export RESTIC_REPOSITORY="rclone::webdav:$BACKUP_DIR"
# Without a passphrase in the keyring, e.g. for another computer's backup,
# restic asks for it
unset RESTIC_PASSWORD_COMMAND
if [ -n "$(backup_secret passphrase "$BACKUP_WEBDAV/$BACKUP_DIR")" ]; then
export RESTIC_PASSWORD_COMMAND="secret-tool lookup coredesktop backup item passphrase url $BACKUP_WEBDAV/$BACKUP_DIR"
fi
else
echo "Backups aren't set up. Run: configure backup" >&2
fi