#!/bin/bash set -euo pipefail SCRIPT_NAME=$(basename "$0") log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $SCRIPT_NAME: $*" >&2 } cd / || exit 1 #UBUNTU_DEST="/mnt/Backup/Ubuntu" UBUNTU_DEST="/mnt/Backup/Ubuntu/Backups" CONTENT_SRC="/mnt/Content" CONTENT_DEST="/mnt/Backup" # helper wrapper: run rsync with low CPU and low I/O priority run_rsync() { local label="$1" shift log "Starting low‑priority rsync ($label)" nice -n 19 ionice -c 3 rsync -avHAX --delete "$@" } # Helper function: Run a command with low CPU and I/O priority run_low_priority() { local label="$1" shift log "Starting low-priority $label..." nice -n 19 ionice -c 3 "$@" } # Function to manage backup lifecycle - keep dailies for the past week, keep weeklies for the past month, keep montlies for 6 months. manage_backups() { #local dir="/mnt/Backup/Ubuntu/Backups" - use UBUNTU_DEST log "Managing backups in $dir..." # Create the directory if it doesn't exist [ ! -d "$UBUNTU_DEST" ] && sudo mkdir -p "$UBUNTU_DEST" # List all .tgz files and sort them by modification time (oldest first) for backup_file in $(sudo ls -1 $UBUNTU_DEST/*.tgz | sort --key=1.2 --reverse); do filename=$(basename "$backup_file") timestamp=$(echo "$filename" | cut -d'-' -f3- | cut -d '.' -f1) # Calculate age in days mtime=$(stat -c %Y "$backup_file") age=$(( ($(date +%s) - $mtime) / (3600 * 24) )) # Extract day, month, and weekday from timestamp day=$(date -d "@$timestamp" +%d) month=$(date -d "@$timestamp" +%m) weekday=$(date -d "@$timestamp" +%w) # Check if backup is less than a week old (daily retention) if [ $age -lt 7 ]; then log "Backup $filename is less than a week old. Keeping." continue fi # Check for weekly backups on Sundays within the last month if [ $weekday == '0' ]; then current_month=$(date +%m) months_since=$(( (current_month - $month) % 12 )) if [ $months_since -lt 1 ]; then log "Backup $filename is a weekly backup on Sunday within the last month. Keeping." continue fi fi # Check for monthly backups on first day of the month within six months if [ $day == '01' ]; then current_month=$(date +%m) months_since=$(( (current_month - $month) % 12 )) if [ $months_since -lt 6 ]; then log "Backup $filename is a monthly backup on the first day within six months. Keeping." continue fi fi # Delete backups older than retention criteria log "Deleting backup: $filename" sudo rm "$backup_file" done } # --- 1. Backup / → /mnt/Backup/Ubuntu (fast, configs + Docker) --- log "Starting tar backup of / → $UBUNTU_DEST (excluding /mnt and pseudo‑dirs)" sudo mkdir -p "$UBUNTU_DEST" # no longer using rsync to backup main filesystem as single file backup using compression works better with remote sync - does not interfere with syncthing state files and folders at the destination #run_rsync "Ubuntu configs & Docker" \ # --exclude-from=/etc/backup-excludes/ubuntu.exclude \ # / "$UBUNTU_DEST"/ # Create a compressed tar backup with timestamp in the filename timestamp=$(date +%Y%m%d-%H%M%S) tar_output="$UBUNTU_DEST/backup-full-$timestamp.tgz" log "Starting backup of /..." run_low_priority "Ubuntu full backup" \ tar -czf "$tar_output" --exclude-from=/etc/backup-excludes/ubuntu.exclude / log "Finished / → $UBUNTU_DEST backup." # --- 2. Backup /mnt/Content → /mnt/Backup (large media‑heavy sync) --- if [ -d "$CONTENT_SRC" ]; then log "Starting rsync of $CONTENT_SRC → $CONTENT_DEST (with excludes)" # using --delete-before to ensure space is freed at destination for new and updated files run_rsync "Content -> Backup (media)" \ --delete-before --exclude-from=/etc/backup-excludes/content.exclude \ "$CONTENT_SRC"/ "$CONTENT_DEST"/ log "Finished $CONTENT_SRC → $CONTENT_DEST backup." else log "WARNING: $CONTENT_SRC not found or not a directory; skipping." fi log "All backups completed."