#!/usr/bin/env bash ################################################################################### ## backup - a script to automate backup and pruning of borg repositories ## Copyright (C) 2026 wytch ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU Affero General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU Affero General Public License for more details. ## ## You should have received a copy of the GNU Affero General Public License ## along with this program. If not, see . ## ################################################################################# ERRORLOG='/var/log/borg/error.log' LOGGING=error # Check if running as root if [ "$EUID" -ne 0 ]; then printf "Error: This script must be run as root (or via sudo).\n" | tee -a $ERRORLOG exit 1 fi # Load the environment variables directly if [ -f /opt/borg/etc/borg_environment ]; then # shellcheck source=/dev/null source /opt/borg/etc/borg_environment # Ensure the variables sourced from the file are exported to child processes export BORG_REPO BORG_PASSPHRASE else printf "Error: /opt/borg/etc/borg_environment not found.\n" | tee -a $ERRORLOG exit 1 fi # Helpers and error handling info() { printf "\n%s %s\n\n" "$(date)" "$*" >&2; } trap 'info "Backup interrupted"; exit 2' INT TERM info "Starting backup for repository: $BORG_REPO" # 1. Create Archive borg create \ --verbose \ --filter AME \ --list \ --stats \ --show-rc \ --compression lz4 \ --exclude-caches \ --exclude 'home/*/.cache/*' \ --exclude 'var/log/journal' \ --exclude 'var/log/borg' \ --exclude 'var/tmp/*' \ --exclude 'var/games' \ --exclude 'home/*/.var/app' \ --exclude 'home/*/Media' \ ::'{hostname}-{now}' \ /etc \ /home \ /root \ /var \ /opt \ 2> >(tee -a $ERRORLOG >&2) backup_exit=$? # 2. Prune old backups info "Pruning repository" borg prune \ --verbose \ --list \ --glob-archives '{hostname}-*' \ --show-rc \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 6 \ 2> >(tee -a $ERRORLOG) prune_exit=$? # 3. Compact repository info "Compacting repository" borg compact --$LOGGING 2> >(tee -a $ERRORLOG >&2) compact_exit=$? # Determine final status code global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) global_exit=$(( compact_exit > global_exit ? compact_exit : global_exit )) if [ "${global_exit}" -eq 0 ]; then info "Backup, Prune, and Compact finished successfully" | tee -a $ERRORLOG elif [ "${global_exit}" -eq 1 ]; then info "Backup, Prune, and/or Compact finished with warnings" | tee -a $ERRORLOG else info "Backup, Prune, and/or Compact finished with errors" | tee -a $ERRORLOG fi exit "${global_exit}"