feat: Add configurable shared backup directory and enhance backup script with improved storage checks

This commit is contained in:
Peter Wood
2025-12-13 16:41:05 -05:00
parent e8ce1f192f
commit 7cbd2779a5
3 changed files with 40 additions and 26 deletions

View File

@@ -6,9 +6,10 @@ UPLOAD_LOCATION=/mnt/share/media/immich/uploads
# Notification settings # Notification settings
WEBHOOK_URL="https://notify.peterwood.rocks/lab" WEBHOOK_URL="https://notify.peterwood.rocks/lab"
SHARED_BACKUP_DIR=/mnt/share/immich-backup
# Backblaze B2 settings # Backblaze B2 settings
# Get these from your B2 account: https://secure.backblaze.com/app_keys.htm # 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_ID=your_key_id_here
# B2_APPLICATION_KEY=your_application_key_here # B2_APPLICATION_KEY=your_application_key_here
# B2_BUCKET_NAME=your_bucket_name_here # B2_BUCKET_NAME=your_bucket_name_here

View File

@@ -56,7 +56,7 @@ Complete backup script for Immich installation that creates backups of:
**Backup Location:** **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` - Database: `immich_db_backup_YYYYMMDD_HHMMSS.sql.gz`
- Uploads: `immich_uploads_YYYYMMDD_HHMMSS.tar.gz` - Uploads: `immich_uploads_YYYYMMDD_HHMMSS.tar.gz`
@@ -66,17 +66,20 @@ Complete backup script for Immich installation that creates backups of:
**Backup Workflow:** **Backup Workflow:**
1. **Create local backups** in temporary directory (`../immich_backups/`) 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) 3. **Upload to Backblaze B2** (if configured)
4. **Delete local copies** (shared storage copies retained) 4. **Delete local copies** (shared storage copies retained)
**Features:** **Features:**
- **Smart backup workflow**: Creates → Copies to shared storage → Uploads to B2 → Cleans up locally - **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) - Command-line options for flexible operation (--help, --dry-run, --no-upload, --verbose)
- Dry-run mode to preview operations without executing - Dry-run mode to preview operations without executing
- Option to skip B2 upload for local-only backups - 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 - **Local cleanup**: Removes temporary files after successful copy to shared storage
- Automatic container pausing/resuming during backup - Automatic container pausing/resuming during backup
- Comprehensive error handling and cleanup - Comprehensive error handling and cleanup
@@ -158,11 +161,11 @@ Container Status Check:
B2 Upload Configuration: B2 Upload Configuration:
✓ B2 configured - would upload to bucket: my-immich-backups ✓ 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 Check:
✓ Shared storage accessible: /mnt/share/media/backups ✓ 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 === === DRY RUN COMPLETE - No files were created or modified ===
``` ```

View File

@@ -148,7 +148,13 @@ while [[ $# -gt 0 ]]; do
done done
# B2 CLI tool path # 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 # Notification function
send_notification() { send_notification() {
@@ -225,11 +231,14 @@ LOG_FILE="${LOG_DIR}/immich-backup.log"
log_message() { log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" 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) # Shared backup directory (can be overridden in .env)
log_status() { SHARED_BACKUP_DIR="${SHARED_BACKUP_DIR:-/mnt/share/media/backups/immich}"
echo "$1" | tee -a "$LOG_FILE"
} # Generate timestamp for the backup filename
# Create backup directory if it doesn't exist # Create backup directory if it doesn't exist
BACKUP_DIR="$(dirname "$0")/../immich_backups" BACKUP_DIR="$(dirname "$0")/../immich_backups"
@@ -307,15 +316,16 @@ if [ "$DRY_RUN" = true ]; then
# Check shared storage directory # Check shared storage directory
echo "" echo ""
echo "Shared Storage Check:" echo "Shared Storage Check:"
if [ -d "/mnt/share/media/backups" ]; then SHARED_PARENT=$(dirname "$SHARED_BACKUP_DIR")
echo " ✓ Shared storage accessible: /mnt/share/media/backups" if [ -d "$SHARED_PARENT" ]; then
if [ -w "/mnt/share/media/backups" ]; then echo " ✓ Shared storage accessible: $SHARED_PARENT"
echo " ✓ Shared storage writable - would copy backups before B2 upload" if [ -w "$SHARED_PARENT" ]; then
echo " ✓ Shared storage writable - would copy backups to $SHARED_BACKUP_DIR"
else else
echo " ⚠ Shared storage not writable - backups would remain in ${BACKUP_DIR}" echo " ⚠ Shared storage not writable - backups would remain in ${BACKUP_DIR}"
fi fi
else else
echo " ⚠ Shared storage not accessible: /mnt/share/media/backups" echo " ⚠ Shared storage not accessible: $SHARED_PARENT"
echo " Backups would remain in ${BACKUP_DIR}" echo " Backups would remain in ${BACKUP_DIR}"
fi fi
@@ -380,7 +390,7 @@ fi
log_message "Taking database backup using pg_dumpall as recommended by Immich documentation..." log_message "Taking database backup using pg_dumpall as recommended by Immich documentation..."
# Use pg_dumpall with recommended flags: --clean and --if-exists # 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 \ --clean \
--if-exists \ --if-exists \
--username="${DB_USERNAME}" \ --username="${DB_USERNAME}" \
@@ -454,22 +464,22 @@ if [ "${IMMICH_SERVER_RUNNING:-true}" = true ]; then
log_message "Note: No need to unpause immich_server container." log_message "Note: No need to unpause immich_server container."
fi fi
fi fi
echo ""
echo "=== COPYING BACKUPS TO SHARED STORAGE ==="
# Update metrics for shared storage phase # Update metrics for shared storage phase
if [[ "$METRICS_ENABLED" == "true" ]]; then if [[ "$METRICS_ENABLED" == "true" ]]; then
metrics_update_status "running" "Copying backups to shared storage" metrics_update_status "running" "Copying backups to shared storage"
fi fi
SHARED_BACKUP_DIR="/mnt/share/media/backups/immich"
# Initialize COPY_SUCCESS before use # Initialize COPY_SUCCESS before use
COPY_SUCCESS=false 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 # 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 "Warning: Failed to create shared backup directory: $SHARED_BACKUP_DIR"
log_message "Backup files remain only in: $BACKUP_DIR" log_message "Backup files remain only in: $BACKUP_DIR"
COPY_SUCCESS=false COPY_SUCCESS=false