#!/usr/bin/env bash set -euo pipefail BACKUP_DIR=/mnt/backups/media DB_BACKUP_DIR="$BACKUP_DIR/backups" LOG="$BACKUP_DIR/backup.log" RETAIN_DAYS=14 mkdir -p "$DB_BACKUP_DIR" echo "[$(date)] Starting Immich backup" >> "$LOG" # 1. Database dump (must come before file sync) DUMP_FILE="$DB_BACKUP_DIR/immich-db-$(date +%Y%m%dT%H%M%S).sql.gz" docker exec immich_postgres pg_dump --clean --if-exists \ --dbname=immich --username=postgres | gzip > "$DUMP_FILE" echo "[$(date)] DB dump: $DUMP_FILE" >> "$LOG" # 2. Rsync critical asset folders (skip thumbs and encoded-video — regeneratable) for DIR in library upload profile; do rsync -a --delete /mnt/media/upload/$DIR/ "$BACKUP_DIR/$DIR/" >> "$LOG" 2>&1 echo "[$(date)] Synced $DIR" >> "$LOG" done # 3. Remove old DB dumps find "$DB_BACKUP_DIR" -name "immich-db-*.sql.gz" -mtime +$RETAIN_DAYS -delete echo "[$(date)] Cleaned dumps older than ${RETAIN_DAYS}d" >> "$LOG" touch "$BACKUP_DIR/.last_sync" echo "[$(date)] Immich backup complete" >> "$LOG"