#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" STACKS_DIR="$(dirname "$SCRIPT_DIR")" DATA_DIR="$STACKS_DIR/.data" DUMP_DIR="$DATA_DIR/backup/dumps" LOG_FILE="$SCRIPT_DIR/backup.log" # Load environment set -a source "$SCRIPT_DIR/.env" set +a export RESTIC_REPOSITORY RESTIC_PASSWORD log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; } notify() { local color="$1" text="$2" curl -sf -o /dev/null -X POST "$MATTERMOST_WEBHOOK" \ -H 'Content-Type: application/json' \ -d "{\"attachments\":[{\"color\":\"$color\",\"text\":\"$text\"}]}" } # Truncate log on each run : > "$LOG_FILE" log "Starting backup" # --- Postgres dumps --- mkdir -p "$DUMP_DIR" declare -A DATABASES=( [umami_db]="umami:umami" [blinko_db]="blinko:blinko" [gitea_db]="gitea:gitea" [mattermost_db]="mattermost:mattermost" [sexy_db]="sexy:sexy" [immich_db]="immich:immich" [coolify_db]="coolify:coolify" ) dump_errors=() for container in "${!DATABASES[@]}"; do IFS=: read -r user db <<< "${DATABASES[$container]}" log "Dumping $db from $container" if docker exec "$container" pg_dump -U "$user" "$db" > "$DUMP_DIR/$db.sql" 2>>"$LOG_FILE"; then log " OK ($(du -h "$DUMP_DIR/$db.sql" | cut -f1))" else log " FAILED: $container" dump_errors+=("$db") fi done if [ ${#dump_errors[@]} -gt 0 ]; then log "WARNING: Failed dumps: ${dump_errors[*]}" fi # --- Restic backup --- log "Running restic backup" if ! restic backup "$DATA_DIR" --tag stacks 2>&1 | tee -a "$LOG_FILE"; then log "FATAL: restic backup failed" notify "#cc0000" ":x: **Backup failed** — restic backup error. Check \`$LOG_FILE\`." exit 1 fi # --- Restic prune --- log "Pruning old snapshots" if ! restic forget --prune --keep-daily 7 --keep-weekly 4 --keep-monthly 6 2>&1 | tee -a "$LOG_FILE"; then log "WARNING: restic forget failed" fi # --- Summary --- snapshot_info=$(restic snapshots --latest 1 --compact 2>/dev/null | tail -3 | head -1) repo_stats=$(restic stats 2>/dev/null | grep "Total Size" || true) summary=":white_check_mark: **Backup complete**" [ ${#dump_errors[@]} -gt 0 ] && summary+="\n:warning: Failed dumps: ${dump_errors[*]}" summary+="\nLatest: \`$snapshot_info\`" [ -n "$repo_stats" ] && summary+="\nRepo: $repo_stats" notify "#36a64f" "$summary" log "Backup complete"