diff --git a/.env.example b/.env.example index 8c214a0..469468a 100644 --- a/.env.example +++ b/.env.example @@ -6,9 +6,10 @@ UPLOAD_LOCATION=/mnt/share/media/immich/uploads # Notification settings WEBHOOK_URL="https://notify.peterwood.rocks/lab" +SHARED_BACKUP_DIR=/mnt/share/immich-backup + # Backblaze B2 settings # Get these from your B2 account: https://secure.backblaze.com/app_keys.htm -K005YB4icG3edh5Z9o64ieXvepEYWoA # B2_APPLICATION_KEY_ID=your_key_id_here # B2_APPLICATION_KEY=your_application_key_here # B2_BUCKET_NAME=your_bucket_name_here diff --git a/immich/README.md b/immich/README.md index 76122f0..90c670b 100644 --- a/immich/README.md +++ b/immich/README.md @@ -56,7 +56,7 @@ Complete backup script for Immich installation that creates backups of: **Backup Location:** -**Primary Storage:** `/mnt/share/media/backups/immich/` (shared storage) +**Primary Storage:** Configurable via `SHARED_BACKUP_DIR` in `.env` (default: `/mnt/share/media/backups/immich/`) - Database: `immich_db_backup_YYYYMMDD_HHMMSS.sql.gz` - Uploads: `immich_uploads_YYYYMMDD_HHMMSS.tar.gz` @@ -66,17 +66,20 @@ Complete backup script for Immich installation that creates backups of: **Backup Workflow:** 1. **Create local backups** in temporary directory (`../immich_backups/`) -2. **Copy to shared storage** (`/mnt/share/media/backups/immich/`) +2. **Copy to shared storage** (configured via `SHARED_BACKUP_DIR`) 3. **Upload to Backblaze B2** (if configured) 4. **Delete local copies** (shared storage copies retained) **Features:** - **Smart backup workflow**: Creates → Copies to shared storage → Uploads to B2 → Cleans up locally +- **Configurable Storage**: Support for custom shared storage paths via `.env` +- **Robust B2 Support**: Automatically detects system-installed `b2` CLI or local binary - Command-line options for flexible operation (--help, --dry-run, --no-upload, --verbose) - Dry-run mode to preview operations without executing - Option to skip B2 upload for local-only backups -- **Shared storage integration**: Automatically copies backups to `/mnt/share/media/backups/immich/` +- **Shared storage integration**: Automatically copies backups to shared storage +- **Safety Checks**: Verifies mount points and storage availability before writing - **Local cleanup**: Removes temporary files after successful copy to shared storage - Automatic container pausing/resuming during backup - Comprehensive error handling and cleanup @@ -158,11 +161,11 @@ Container Status Check: B2 Upload Configuration: ✓ B2 configured - would upload to bucket: my-immich-backups - ✓ B2 CLI found at: /home/acedanger/shell/immich/b2-linux + ✓ B2 CLI found at: /usr/bin/b2 Shared Storage Check: ✓ Shared storage accessible: /mnt/share/media/backups - ✓ Shared storage writable - would copy backups before B2 upload + ✓ Shared storage writable - would copy backups to /mnt/share/media/backups/immich/ === DRY RUN COMPLETE - No files were created or modified === ``` diff --git a/immich/backup-immich.sh b/immich/backup-immich.sh index 6642684..c472a47 100755 --- a/immich/backup-immich.sh +++ b/immich/backup-immich.sh @@ -148,7 +148,13 @@ while [[ $# -gt 0 ]]; do done # B2 CLI tool path -B2_CLI="$(dirname "$0")/b2-linux" +if [ -f "$(dirname "$0")/b2-linux" ]; then + B2_CLI="$(dirname "$0")/b2-linux" +elif command -v b2 &> /dev/null; then + B2_CLI=$(command -v b2) +else + B2_CLI="$(dirname "$0")/b2-linux" +fi # Notification function send_notification() { @@ -225,11 +231,14 @@ LOG_FILE="${LOG_DIR}/immich-backup.log" log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" } +# Create backup directory if it doesn't exist +BACKUP_DIR="$(dirname "$0")/../immich_backups" +mkdir -p "$BACKUP_DIR" -# Function to log without timestamp (for progress/status) -log_status() { - echo "$1" | tee -a "$LOG_FILE" -} +# Shared backup directory (can be overridden in .env) +SHARED_BACKUP_DIR="${SHARED_BACKUP_DIR:-/mnt/share/media/backups/immich}" + +# Generate timestamp for the backup filename # Create backup directory if it doesn't exist BACKUP_DIR="$(dirname "$0")/../immich_backups" @@ -307,15 +316,16 @@ if [ "$DRY_RUN" = true ]; then # Check shared storage directory echo "" echo "Shared Storage Check:" - if [ -d "/mnt/share/media/backups" ]; then - echo " ✓ Shared storage accessible: /mnt/share/media/backups" - if [ -w "/mnt/share/media/backups" ]; then - echo " ✓ Shared storage writable - would copy backups before B2 upload" + SHARED_PARENT=$(dirname "$SHARED_BACKUP_DIR") + if [ -d "$SHARED_PARENT" ]; then + echo " ✓ Shared storage accessible: $SHARED_PARENT" + if [ -w "$SHARED_PARENT" ]; then + echo " ✓ Shared storage writable - would copy backups to $SHARED_BACKUP_DIR" else echo " ⚠ Shared storage not writable - backups would remain in ${BACKUP_DIR}" fi else - echo " ⚠ Shared storage not accessible: /mnt/share/media/backups" + echo " ⚠ Shared storage not accessible: $SHARED_PARENT" echo " Backups would remain in ${BACKUP_DIR}" fi @@ -380,7 +390,7 @@ fi log_message "Taking database backup using pg_dumpall as recommended by Immich documentation..." # Use pg_dumpall with recommended flags: --clean and --if-exists -if ! docker exec -t immich_postgres pg_dumpall \ +if ! docker exec immich_postgres pg_dumpall \ --clean \ --if-exists \ --username="${DB_USERNAME}" \ @@ -454,22 +464,22 @@ if [ "${IMMICH_SERVER_RUNNING:-true}" = true ]; then log_message "Note: No need to unpause immich_server container." fi fi - -echo "" -echo "=== COPYING BACKUPS TO SHARED STORAGE ===" - # Update metrics for shared storage phase if [[ "$METRICS_ENABLED" == "true" ]]; then metrics_update_status "running" "Copying backups to shared storage" fi -SHARED_BACKUP_DIR="/mnt/share/media/backups/immich" - # Initialize COPY_SUCCESS before use COPY_SUCCESS=false +# Check if the parent directory of the shared backup dir exists (basic mount check) +SHARED_PARENT=$(dirname "$SHARED_BACKUP_DIR") +if [ ! -d "$SHARED_PARENT" ]; then + log_message "Warning: Shared storage parent directory not found: $SHARED_PARENT" + log_message "Backup files remain only in: $BACKUP_DIR" + COPY_SUCCESS=false # Create shared backup directory if it doesn't exist -if ! mkdir -p "$SHARED_BACKUP_DIR"; then +elif ! mkdir -p "$SHARED_BACKUP_DIR"; then log_message "Warning: Failed to create shared backup directory: $SHARED_BACKUP_DIR" log_message "Backup files remain only in: $BACKUP_DIR" COPY_SUCCESS=false @@ -533,12 +543,12 @@ if [ "$NO_UPLOAD" = true ]; then B2_UPLOAD_SUCCESS="skipped" else echo "=== UPLOADING TO BACKBLAZE B2 ===" - + # Update metrics for B2 upload phase if [[ "$METRICS_ENABLED" == "true" ]]; then metrics_update_status "running" "Uploading backups to Backblaze B2" fi - + B2_UPLOAD_SUCCESS=true # Upload database backup from local location