From 15ac19d32d08ec386ccd9861c2631d5801a7c238 Mon Sep 17 00:00:00 2001 From: wytch Date: Wed, 14 Jan 2026 13:48:23 -0600 Subject: [PATCH] first commit --- borg/bin/backup | 80 ++++++++++++++++++++++ borg/bin/reposetup | 47 +++++++++++++ borg/etc/borg_environment | 6 ++ install.sh | 139 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+) create mode 100755 borg/bin/backup create mode 100644 borg/bin/reposetup create mode 100644 borg/etc/borg_environment create mode 100755 install.sh diff --git a/borg/bin/backup b/borg/bin/backup new file mode 100755 index 0000000..5ef1b22 --- /dev/null +++ b/borg/bin/backup @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + printf "Error: This script must be run as root (or via sudo).\n" + 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" + 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/tmp/*' \ + --exclude 'var/games' \ + --exclude 'home/*/Media' \ + --progress \ + ::'{hostname}-{now}' \ + /etc \ + /home \ + /root \ + /var \ + /opt + +backup_exit=$? + +# 2. Prune old backups +info "Pruning repository" +borg prune \ + --list \ + --glob-archives '{hostname}-*' \ + --show-rc \ + --keep-daily 7 \ + --keep-weekly 4 \ + --keep-monthly 6 + +prune_exit=$? + +# 3. Compact repository +info "Compacting repository" +borg compact + +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" +elif [ "${global_exit}" -eq 1 ]; then + info "Backup, Prune, and/or Compact finished with warnings" +else + info "Backup, Prune, and/or Compact finished with errors" +fi + +exit "${global_exit}" diff --git a/borg/bin/reposetup b/borg/bin/reposetup new file mode 100644 index 0000000..c29c661 --- /dev/null +++ b/borg/bin/reposetup @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Ensure running as root to read the environment file +if [ "$EUID" -ne 0 ]; then + printf "Error: This script must be run as root (or via sudo).\n" + exit 1 +fi + +# Load the environment variables +if [ -f /opt/borg/etc/borg_environment ]; then + # shellcheck source=/dev/null + source /opt/borg/etc/borg_environment + export BORG_REPO BORG_PASSPHRASE +else + printf "Error: /opt/borg/etc/borg_environment not found.\n" + exit 1 +fi + +printf "Checking repository status at: %s\n" "$BORG_REPO" + +# Check if the repo already exists to prevent accidental re-init +if borg info >/dev/null 2>&1; then + printf "Error: Repository already exists and is initialized.\n" + exit 1 +fi + +printf "Initializing repository...\n" + +# Logic for encryption mode based on whether a passphrase exists +if [ -z "$BORG_PASSPHRASE" ]; then + printf "No passphrase detected. Initializing with 'none' encryption.\n" + borg init --encryption=none +else + printf "Passphrase detected. Initializing with 'repokey' encryption.\n" + # repokey stores the key inside the repository config, protected by the passphrase + borg init --encryption=repokey +fi + +init_exit=$? + +if [ "$init_exit" -eq 0 ]; then + printf "\nSuccess: Repository initialized successfully.\n" + printf "You can now run your first backup using: sudo /opt/borg/bin/backup\n" +else + printf "\nError: Repository initialization failed (Exit code: %s).\n" "$init_exit" + exit "$init_exit" +fi diff --git a/borg/etc/borg_environment b/borg/etc/borg_environment new file mode 100644 index 0000000..26c0de4 --- /dev/null +++ b/borg/etc/borg_environment @@ -0,0 +1,6 @@ +# Setting this, so the repo does not need to be given on the commandline: +export BORG_REPO=REPOPATH + +# See the section "Passphrase notes" for more infos. +export BORG_PASSPHRASE='REPOPASSPHRASE' + diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..71ad01d --- /dev/null +++ b/install.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash + +set -e + +# ... (include validate_borg_url, escape_sed, etc. from previous steps) + +generate_recovery_file() { + local repo="$1" + local pass="$2" + local timestamp=$(date +%Y%m%d_%H%M%S) + local recovery_file="$HOME/borg_recovery_$timestamp.txt" + + { + echo "BORG BACKUP RECOVERY INFORMATION" + echo "Generated on: $(date)" + echo "--------------------------------" + echo "REPOSITORY URL: $repo" + echo "PASSPHRASE: $pass" + echo "--------------------------------" + echo "Keep this file in a safe, offline location." + } > "$recovery_file" + + chmod 600 "$recovery_file" + printf "\nCRITICAL: Recovery information saved to: $recovery_file\n" + printf "Please move this to a secure location (e.g., a password manager or physical safe).\n" +} + +# Validation function for Borg Repository URLs +validate_borg_url() { + local url="$1" + # Regex covers: + # 1. Local absolute/home paths (/... or ~/...) + # 2. SSH shortcuts (user@host:path) + # 3. Explicit protocols (ssh://, file://) + local regex="^(/|~/|([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+:)|([a-z]+://)).+" + + if [[ $url =~ $regex ]]; then + return 0 + else + return 1 + fi +} + +escape_sed() { + printf '%s\n' "$1" | sed -e 's/[]\/$*.^|[]/\\&/g' +} + +setup_backup () { + local repopath="$1" + local raw_passphrase="$2" + + printf "\nInstalling backup script environment. You will be prompted for your sudo password.\n" + + # Check if the source directory exists before copying + if [ ! -d "borg" ]; then + printf "Error: 'borg' source directory not found in current location.\n" + exit 1 + fi + + sudo cp -r borg /opt/ + sudo chown -R "root:root" /opt/borg + sudo chmod -R 755 /opt/borg + sudo chmod 700 /opt/borg/etc + + local escaped_path=$(escape_sed "$repopath") + local escaped_pass=$(escape_sed "$raw_passphrase") + + sudo sed -i -f - /opt/borg/etc/borg_environment <