mirror of
https://github.com/acedanger/shell.git
synced 2025-12-06 01:10:12 -08:00
feat: Enhance backup script documentation and workflow for shared storage integration
This commit is contained in:
@@ -56,16 +56,31 @@ Complete backup script for Immich installation that creates backups of:
|
|||||||
|
|
||||||
**Backup Location:**
|
**Backup Location:**
|
||||||
|
|
||||||
- Database: `../immich_backups/immich_db_backup_YYYYMMDD_HHMMSS.sql.gz`
|
**Primary Storage:** `/mnt/share/media/backups/immich/` (shared storage)
|
||||||
- Uploads: `../immich_backups/immich_uploads_YYYYMMDD_HHMMSS.tar.gz`
|
|
||||||
|
- Database: `immich_db_backup_YYYYMMDD_HHMMSS.sql.gz`
|
||||||
|
- Uploads: `immich_uploads_YYYYMMDD_HHMMSS.tar.gz`
|
||||||
|
|
||||||
|
**Temporary Location:** `../immich_backups/` (cleaned up after copy to shared storage)
|
||||||
|
|
||||||
|
**Backup Workflow:**
|
||||||
|
|
||||||
|
1. **Create local backups** in temporary directory (`../immich_backups/`)
|
||||||
|
2. **Copy to shared storage** (`/mnt/share/media/backups/immich/`)
|
||||||
|
3. **Upload to Backblaze B2** (if configured)
|
||||||
|
4. **Delete local copies** (shared storage copies retained)
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
|
|
||||||
|
- **Smart backup workflow**: Creates → Copies to shared storage → Uploads to B2 → Cleans up locally
|
||||||
- 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/`
|
||||||
|
- **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
|
||||||
|
- **Graceful degradation**: Retains local backups if shared storage copy fails
|
||||||
- Backup validation and health checks
|
- Backup validation and health checks
|
||||||
- Automatic compression
|
- Automatic compression
|
||||||
- Old backup cleanup (configurable)
|
- Old backup cleanup (configurable)
|
||||||
@@ -130,6 +145,12 @@ Would create:
|
|||||||
- Database backup: /home/acedanger/shell/immich_backups/immich_db_backup_20250527_140000.sql.gz
|
- Database backup: /home/acedanger/shell/immich_backups/immich_db_backup_20250527_140000.sql.gz
|
||||||
- Upload backup: /home/acedanger/shell/immich_backups/immich_uploads_20250527_140000.tar.gz
|
- Upload backup: /home/acedanger/shell/immich_backups/immich_uploads_20250527_140000.tar.gz
|
||||||
|
|
||||||
|
Workflow:
|
||||||
|
1. Create local backups
|
||||||
|
2. Copy to shared storage: /mnt/share/media/backups/immich/
|
||||||
|
3. Upload to B2 (if configured)
|
||||||
|
4. Delete local backups (keep shared copies)
|
||||||
|
|
||||||
Container Status Check:
|
Container Status Check:
|
||||||
✓ immich_server: Running (would pause during backup)
|
✓ immich_server: Running (would pause during backup)
|
||||||
✓ immich_postgres: Running
|
✓ immich_postgres: Running
|
||||||
@@ -139,6 +160,10 @@ 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: /home/acedanger/shell/immich/b2-linux
|
||||||
|
|
||||||
|
Shared Storage Check:
|
||||||
|
✓ Shared storage accessible: /mnt/share/media/backups
|
||||||
|
✓ Shared storage writable - would copy backups before B2 upload
|
||||||
|
|
||||||
=== DRY RUN COMPLETE - No files were created or modified ===
|
=== DRY RUN COMPLETE - No files were created or modified ===
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -283,12 +308,39 @@ WEBHOOK_URL="https://notify.peterwood.rocks/lab"
|
|||||||
BACKUP_RETENTION_DAYS=30
|
BACKUP_RETENTION_DAYS=30
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Shared Storage Configuration
|
||||||
|
|
||||||
|
The backup script automatically uses shared storage at `/mnt/share/media/backups/immich/` for permanent backup storage. This provides:
|
||||||
|
|
||||||
|
- **Centralized storage**: All backups stored in one accessible location
|
||||||
|
- **Network accessibility**: Backups available across your network
|
||||||
|
- **Space efficiency**: Temporary local files are cleaned up after copying
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
|
||||||
|
- `/mnt/share/media/backups/` directory must be accessible and writable
|
||||||
|
- Sufficient disk space for backup files (database + uploads archive)
|
||||||
|
|
||||||
|
**Fallback behavior:**
|
||||||
|
|
||||||
|
- If shared storage is inaccessible, backups remain in local temporary directory
|
||||||
|
- Script logs warnings but continues operation
|
||||||
|
- B2 upload still functions from local files if configured
|
||||||
|
|
||||||
## Backup Strategy
|
## Backup Strategy
|
||||||
|
|
||||||
Based on Immich's official backup recommendations:
|
**Workflow Process:**
|
||||||
|
|
||||||
|
1. **Local Creation**: Backups created in temporary directory (`../immich_backups/`)
|
||||||
|
2. **Shared Storage Copy**: Files copied to `/mnt/share/media/backups/immich/`
|
||||||
|
3. **B2 Upload**: Local files uploaded to Backblaze B2 (if configured)
|
||||||
|
4. **Local Cleanup**: Temporary files deleted after successful copy to shared storage
|
||||||
|
|
||||||
|
**Backup Content** (based on Immich's official recommendations):
|
||||||
|
|
||||||
1. **Database Backup**: Uses `pg_dumpall` with `--clean` and `--if-exists` flags
|
1. **Database Backup**: Uses `pg_dumpall` with `--clean` and `--if-exists` flags
|
||||||
2. **Upload Directory**: Complete archive of upload location including:
|
2. **Upload Directory**: Complete archive of upload location including:
|
||||||
|
|
||||||
- upload/ - Original photos and videos
|
- upload/ - Original photos and videos
|
||||||
- profile/ - User profile images
|
- profile/ - User profile images
|
||||||
- thumbs/ - Generated thumbnails
|
- thumbs/ - Generated thumbnails
|
||||||
@@ -296,6 +348,12 @@ Based on Immich's official backup recommendations:
|
|||||||
- library/ - Library metadata
|
- library/ - Library metadata
|
||||||
- backups/ - Existing backup files (excluded from new backups)
|
- backups/ - Existing backup files (excluded from new backups)
|
||||||
|
|
||||||
|
**Safety Features:**
|
||||||
|
|
||||||
|
- **Graceful degradation**: If shared storage fails, keeps local backups
|
||||||
|
- **Error isolation**: B2 upload failure doesn't affect local or shared storage
|
||||||
|
- **Container safety**: Immich server paused during backup to ensure consistency
|
||||||
|
|
||||||
## Notifications 🔔
|
## Notifications 🔔
|
||||||
|
|
||||||
The backup script sends notifications to your webhook URL with:
|
The backup script sends notifications to your webhook URL with:
|
||||||
@@ -310,6 +368,7 @@ Example notification:
|
|||||||
```text
|
```text
|
||||||
📦 Database: immich_db_backup_20250526_215913.sql.gz (150MB)
|
📦 Database: immich_db_backup_20250526_215913.sql.gz (150MB)
|
||||||
📁 Uploads: immich_uploads_20250526_215913.tar.gz (25GB)
|
📁 Uploads: immich_uploads_20250526_215913.tar.gz (25GB)
|
||||||
|
💾 Stored in: /mnt/share/media/backups/immich (local files cleaned up)
|
||||||
☁️ Successfully uploaded to B2 bucket: my-immich-backups
|
☁️ Successfully uploaded to B2 bucket: my-immich-backups
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -346,16 +405,35 @@ The B2 CLI tool (`b2-linux`) is included in this directory and doesn't require s
|
|||||||
|
|
||||||
For complete restore instructions, see: <https://immich.app/docs/administration/backup-and-restore/>
|
For complete restore instructions, see: <https://immich.app/docs/administration/backup-and-restore/>
|
||||||
|
|
||||||
|
**Backup File Locations:**
|
||||||
|
|
||||||
|
- **Primary**: `/mnt/share/media/backups/immich/` (shared storage)
|
||||||
|
- **Fallback**: `../immich_backups/` (if shared storage copy failed)
|
||||||
|
- **Cloud**: Backblaze B2 bucket (if B2 upload was configured)
|
||||||
|
|
||||||
|
**Restore Steps:**
|
||||||
|
|
||||||
1. **Database Restore:**
|
1. **Database Restore:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker exec -i immich_postgres psql -U postgres < immich_db_backup.sql
|
# From shared storage (primary location)
|
||||||
|
docker exec -i immich_postgres psql -U postgres < /mnt/share/media/backups/immich/immich_db_backup_YYYYMMDD_HHMMSS.sql
|
||||||
|
|
||||||
|
# OR from B2 download
|
||||||
|
./b2-linux download-file-by-name your-bucket immich-backups/immich_db_backup_YYYYMMDD_HHMMSS.sql.gz
|
||||||
|
gunzip immich_db_backup_YYYYMMDD_HHMMSS.sql.gz
|
||||||
|
docker exec -i immich_postgres psql -U postgres < immich_db_backup_YYYYMMDD_HHMMSS.sql
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Upload Directory Restore:**
|
2. **Upload Directory Restore:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tar -xzf immich_uploads_backup.tar.gz -C /target/location
|
# From shared storage (primary location)
|
||||||
|
tar -xzf /mnt/share/media/backups/immich/immich_uploads_YYYYMMDD_HHMMSS.tar.gz -C /target/location
|
||||||
|
|
||||||
|
# OR from B2 download
|
||||||
|
./b2-linux download-file-by-name your-bucket immich-backups/immich_uploads_YYYYMMDD_HHMMSS.tar.gz
|
||||||
|
tar -xzf immich_uploads_YYYYMMDD_HHMMSS.tar.gz -C /target/location
|
||||||
```
|
```
|
||||||
|
|
||||||
## Logs
|
## Logs
|
||||||
|
|||||||
@@ -233,6 +233,12 @@ if [ "$DRY_RUN" = true ]; then
|
|||||||
echo " - Database backup: ${DB_BACKUP_PATH}.gz"
|
echo " - Database backup: ${DB_BACKUP_PATH}.gz"
|
||||||
echo " - Upload backup: ${UPLOAD_BACKUP_PATH}"
|
echo " - Upload backup: ${UPLOAD_BACKUP_PATH}"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo "Workflow:"
|
||||||
|
echo " 1. Create local backups"
|
||||||
|
echo " 2. Copy to shared storage: /mnt/share/media/backups/immich/"
|
||||||
|
echo " 3. Upload to B2 (if configured)"
|
||||||
|
echo " 4. Delete local backups (keep shared copies)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Check container status in dry-run
|
# Check container status in dry-run
|
||||||
echo "Container Status Check:"
|
echo "Container Status Check:"
|
||||||
@@ -274,6 +280,21 @@ if [ "$DRY_RUN" = true ]; then
|
|||||||
echo " ! B2 not configured - would skip upload"
|
echo " ! B2 not configured - would skip upload"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
else
|
||||||
|
echo " ⚠ Shared storage not writable - backups would remain in ${BACKUP_DIR}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ⚠ Shared storage not accessible: /mnt/share/media/backups"
|
||||||
|
echo " Backups would remain in ${BACKUP_DIR}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== DRY RUN COMPLETE - No files were created or modified ==="
|
echo "=== DRY RUN COMPLETE - No files were created or modified ==="
|
||||||
exit 0
|
exit 0
|
||||||
@@ -319,20 +340,6 @@ if ! docker ps -q --filter "name=immich_postgres" | grep -q .; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if the Immich server container exists and is running
|
|
||||||
log_status "Checking immich_server container status..."
|
|
||||||
if docker ps -q --filter "name=immich_server" | grep -q .; then
|
|
||||||
log_message "Pausing immich_server container to minimize database writes during backup..."
|
|
||||||
if ! docker pause immich_server; then
|
|
||||||
log_message "Failed to pause immich_server container."
|
|
||||||
# Continue with backup instead of exiting
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_message "Note: immich_server container not found or not running. Continuing with backup anyway."
|
|
||||||
# Set a flag so we don't try to unpause it later
|
|
||||||
IMMICH_SERVER_RUNNING=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== PHASE 1: DATABASE BACKUP ==="
|
echo "=== PHASE 1: DATABASE BACKUP ==="
|
||||||
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..."
|
||||||
@@ -393,23 +400,65 @@ if [ "${IMMICH_SERVER_RUNNING:-true}" = true ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Resume the Immich server only if it was running and we paused it
|
echo ""
|
||||||
if [ "${IMMICH_SERVER_RUNNING:-true}" = true ]; then
|
echo "=== COPYING BACKUPS TO SHARED STORAGE ==="
|
||||||
log_status "Resuming immich_server container..."
|
SHARED_BACKUP_DIR="/mnt/share/media/backups/immich"
|
||||||
if ! docker unpause immich_server 2>/dev/null; then
|
|
||||||
log_message "Note: No need to unpause immich_server container."
|
# Initialize COPY_SUCCESS before use
|
||||||
|
COPY_SUCCESS=false
|
||||||
|
|
||||||
|
# Create shared backup directory if it doesn't exist
|
||||||
|
if ! 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
|
||||||
|
else
|
||||||
|
log_message "Copying backup files to shared storage: $SHARED_BACKUP_DIR"
|
||||||
|
COPY_SUCCESS=true
|
||||||
|
|
||||||
|
# Copy database backup
|
||||||
|
if [ -f "${DB_BACKUP_PATH}.gz" ]; then
|
||||||
|
if cp "${DB_BACKUP_PATH}.gz" "$SHARED_BACKUP_DIR/"; then
|
||||||
|
log_message "✅ Copied database backup to shared storage"
|
||||||
|
else
|
||||||
|
log_message "❌ Failed to copy database backup to shared storage"
|
||||||
|
COPY_SUCCESS=false
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy uploads backup
|
||||||
|
if [ -f "${UPLOAD_BACKUP_PATH}" ]; then
|
||||||
|
if cp "${UPLOAD_BACKUP_PATH}" "$SHARED_BACKUP_DIR/"; then
|
||||||
|
log_message "✅ Copied uploads backup to shared storage"
|
||||||
|
else
|
||||||
|
log_message "❌ Failed to copy uploads backup to shared storage"
|
||||||
|
COPY_SUCCESS=false
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$COPY_SUCCESS" = true ]; then
|
||||||
|
log_message "All backup files successfully copied to shared storage"
|
||||||
|
else
|
||||||
|
log_message "Some backup files failed to copy to shared storage"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== BACKUP COMPLETED SUCCESSFULLY! ==="
|
|
||||||
echo "Database backup saved to: ${DB_BACKUP_PATH}.gz"
|
|
||||||
echo "Upload directory backup saved to: ${UPLOAD_BACKUP_PATH}"
|
|
||||||
|
|
||||||
# Calculate backup sizes
|
# Calculate backup sizes
|
||||||
DB_BACKUP_SIZE=$(du -h "${DB_BACKUP_PATH}.gz" 2>/dev/null | cut -f1 || echo "Unknown")
|
DB_BACKUP_SIZE=$(du -h "${DB_BACKUP_PATH}.gz" 2>/dev/null | cut -f1 || echo "Unknown")
|
||||||
UPLOAD_BACKUP_SIZE=$(du -h "${UPLOAD_BACKUP_PATH}" 2>/dev/null | cut -f1 || echo "Unknown")
|
UPLOAD_BACKUP_SIZE=$(du -h "${UPLOAD_BACKUP_PATH}" 2>/dev/null | cut -f1 || echo "Unknown")
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== BACKUP COMPLETED SUCCESSFULLY! ==="
|
||||||
|
if [ "$COPY_SUCCESS" = true ]; then
|
||||||
|
echo "Database backup saved to: ${SHARED_BACKUP_DIR}/$(basename "${DB_BACKUP_PATH}.gz")"
|
||||||
|
echo "Upload directory backup saved to: ${SHARED_BACKUP_DIR}/$(basename "${UPLOAD_BACKUP_PATH}")"
|
||||||
|
echo "(Local backup files have been cleaned up)"
|
||||||
|
else
|
||||||
|
echo "Database backup saved to: ${DB_BACKUP_PATH}.gz"
|
||||||
|
echo "Upload directory backup saved to: ${UPLOAD_BACKUP_PATH}"
|
||||||
|
echo "(Local backup files retained due to copy failure)"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== BACKUP SUMMARY ==="
|
echo "=== BACKUP SUMMARY ==="
|
||||||
echo "Database backup size: ${DB_BACKUP_SIZE}"
|
echo "Database backup size: ${DB_BACKUP_SIZE}"
|
||||||
@@ -425,23 +474,70 @@ else
|
|||||||
echo "=== UPLOADING TO BACKBLAZE B2 ==="
|
echo "=== UPLOADING TO BACKBLAZE B2 ==="
|
||||||
B2_UPLOAD_SUCCESS=true
|
B2_UPLOAD_SUCCESS=true
|
||||||
|
|
||||||
# Upload database backup
|
# Upload database backup from local location
|
||||||
if ! upload_to_b2 "${DB_BACKUP_PATH}.gz"; then
|
if ! upload_to_b2 "${DB_BACKUP_PATH}.gz"; then
|
||||||
B2_UPLOAD_SUCCESS=false
|
B2_UPLOAD_SUCCESS=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Upload uploads backup
|
# Upload uploads backup from local location
|
||||||
if ! upload_to_b2 "${UPLOAD_BACKUP_PATH}"; then
|
if ! upload_to_b2 "${UPLOAD_BACKUP_PATH}"; then
|
||||||
B2_UPLOAD_SUCCESS=false
|
B2_UPLOAD_SUCCESS=false
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Clean up local backup files after successful copy and B2 upload
|
||||||
|
echo ""
|
||||||
|
echo "=== CLEANING UP LOCAL BACKUPS ==="
|
||||||
|
if [ "$COPY_SUCCESS" = true ]; then
|
||||||
|
log_message "Removing local backup files (copies exist in shared storage)..."
|
||||||
|
|
||||||
|
# Remove local database backup
|
||||||
|
if [ -f "${DB_BACKUP_PATH}.gz" ]; then
|
||||||
|
if rm "${DB_BACKUP_PATH}.gz"; then
|
||||||
|
log_message "✅ Removed local database backup"
|
||||||
|
else
|
||||||
|
log_message "⚠ Failed to remove local database backup: ${DB_BACKUP_PATH}.gz"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove local uploads backup
|
||||||
|
if [ -f "${UPLOAD_BACKUP_PATH}" ]; then
|
||||||
|
if rm "${UPLOAD_BACKUP_PATH}"; then
|
||||||
|
log_message "✅ Removed local uploads backup"
|
||||||
|
else
|
||||||
|
log_message "⚠ Failed to remove local uploads backup: ${UPLOAD_BACKUP_PATH}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_message "Local cleanup completed - backups are now in shared storage"
|
||||||
|
|
||||||
|
# Store original paths for health checks before updating
|
||||||
|
ORIGINAL_DB_PATH="${DB_BACKUP_PATH}.gz"
|
||||||
|
ORIGINAL_UPLOAD_PATH="${UPLOAD_BACKUP_PATH}"
|
||||||
|
else
|
||||||
|
log_message "Skipping local cleanup - copy to shared storage failed"
|
||||||
|
log_message "Local backup files retained in: $BACKUP_DIR"
|
||||||
|
|
||||||
|
# Keep original paths for health checks
|
||||||
|
ORIGINAL_DB_PATH="${DB_BACKUP_PATH}.gz"
|
||||||
|
ORIGINAL_UPLOAD_PATH="${UPLOAD_BACKUP_PATH}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Prepare notification message
|
# Prepare notification message
|
||||||
DB_FILENAME=$(basename "${DB_BACKUP_PATH}.gz")
|
DB_FILENAME=$(basename "${DB_BACKUP_PATH}" .gz)
|
||||||
UPLOAD_FILENAME=$(basename "${UPLOAD_BACKUP_PATH}")
|
UPLOAD_FILENAME=$(basename "${UPLOAD_BACKUP_PATH}")
|
||||||
NOTIFICATION_MESSAGE="📦 Database: ${DB_FILENAME} (${DB_BACKUP_SIZE})
|
NOTIFICATION_MESSAGE="📦 Database: ${DB_FILENAME} (${DB_BACKUP_SIZE})
|
||||||
📁 Uploads: ${UPLOAD_FILENAME} (${UPLOAD_BACKUP_SIZE})"
|
📁 Uploads: ${UPLOAD_FILENAME} (${UPLOAD_BACKUP_SIZE})"
|
||||||
|
|
||||||
|
# Add storage location info to notification
|
||||||
|
if [ "$COPY_SUCCESS" = true ]; then
|
||||||
|
NOTIFICATION_MESSAGE="${NOTIFICATION_MESSAGE}
|
||||||
|
💾 Stored in: ${SHARED_BACKUP_DIR} (local files cleaned up)"
|
||||||
|
else
|
||||||
|
NOTIFICATION_MESSAGE="${NOTIFICATION_MESSAGE}
|
||||||
|
💾 Located in: ${BACKUP_DIR} (copy to shared storage failed)"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$B2_UPLOAD_SUCCESS" = "skipped" ]; then
|
if [ "$B2_UPLOAD_SUCCESS" = "skipped" ]; then
|
||||||
NOTIFICATION_MESSAGE="${NOTIFICATION_MESSAGE}
|
NOTIFICATION_MESSAGE="${NOTIFICATION_MESSAGE}
|
||||||
💾 Local backup only (B2 upload skipped)"
|
💾 Local backup only (B2 upload skipped)"
|
||||||
@@ -461,17 +557,30 @@ fi
|
|||||||
# Show backup information
|
# Show backup information
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== BACKUP INVENTORY ==="
|
echo "=== BACKUP INVENTORY ==="
|
||||||
find "${BACKUP_DIR}" -name "*.gz" | wc -l | xargs echo "Total number of backup files:"
|
if [ "$COPY_SUCCESS" = true ]; then
|
||||||
du -sh "${BACKUP_DIR}" | cut -f1 | xargs echo "Total backup directory size:"
|
INVENTORY_DIR="$SHARED_BACKUP_DIR"
|
||||||
|
echo "Backup location: $SHARED_BACKUP_DIR"
|
||||||
|
else
|
||||||
|
INVENTORY_DIR="$BACKUP_DIR"
|
||||||
|
echo "Backup location: $BACKUP_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
find "${INVENTORY_DIR}" -name "*.gz" -o -name "*.tar.gz" | wc -l | xargs echo "Total number of backup files:"
|
||||||
|
du -sh "${INVENTORY_DIR}" | cut -f1 | xargs echo "Total backup directory size:"
|
||||||
|
|
||||||
# List recent backups
|
# List recent backups
|
||||||
echo ""
|
echo ""
|
||||||
echo "Recent backups:"
|
echo "Recent backups:"
|
||||||
find "${BACKUP_DIR}" -name "*.gz" -mtime -7 | sort
|
find "${INVENTORY_DIR}" -name "*.gz" -o -name "*.tar.gz" -mtime -7 | sort
|
||||||
|
|
||||||
# Health check: Verify backup file sizes
|
# Health check: Verify backup file sizes
|
||||||
DB_BACKUP_SIZE_KB=$(du -k "${DB_BACKUP_PATH}.gz" 2>/dev/null | cut -f1 || echo "0")
|
if [ "$COPY_SUCCESS" = true ]; then
|
||||||
UPLOAD_BACKUP_SIZE_KB=$(du -k "${UPLOAD_BACKUP_PATH}" 2>/dev/null | cut -f1 || echo "0")
|
DB_BACKUP_SIZE_KB=$(du -k "${SHARED_BACKUP_DIR}/$(basename "${ORIGINAL_DB_PATH}")" 2>/dev/null | cut -f1 || echo "0")
|
||||||
|
UPLOAD_BACKUP_SIZE_KB=$(du -k "${SHARED_BACKUP_DIR}/$(basename "${ORIGINAL_UPLOAD_PATH}")" 2>/dev/null | cut -f1 || echo "0")
|
||||||
|
else
|
||||||
|
DB_BACKUP_SIZE_KB=$(du -k "${ORIGINAL_DB_PATH}" 2>/dev/null | cut -f1 || echo "0")
|
||||||
|
UPLOAD_BACKUP_SIZE_KB=$(du -k "${ORIGINAL_UPLOAD_PATH}" 2>/dev/null | cut -f1 || echo "0")
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== BACKUP VALIDATION ==="
|
echo "=== BACKUP VALIDATION ==="
|
||||||
@@ -490,21 +599,29 @@ fi
|
|||||||
# Optional: Remove old backups (older than 30 days)
|
# Optional: Remove old backups (older than 30 days)
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== CLEANUP ==="
|
echo "=== CLEANUP ==="
|
||||||
OLD_BACKUPS=$(find "${BACKUP_DIR}" -name "*.gz" -mtime +30 | wc -l)
|
OLD_BACKUPS=$(find "${INVENTORY_DIR}" -name "*.gz" -o -name "*.tar.gz" -mtime +30 | wc -l)
|
||||||
if [ "${OLD_BACKUPS}" -gt 0 ]; then
|
if [ "${OLD_BACKUPS}" -gt 0 ]; then
|
||||||
echo "Found ${OLD_BACKUPS} backup files older than 30 days."
|
echo "Found ${OLD_BACKUPS} backup files older than 30 days in ${INVENTORY_DIR}."
|
||||||
echo "To remove them automatically, uncomment the cleanup line in this script."
|
echo "To remove them automatically, uncomment the cleanup line in this script."
|
||||||
# Uncomment the next line to automatically remove old backups
|
# Uncomment the next line to automatically remove old backups
|
||||||
# find "${BACKUP_DIR}" -name "*.gz" -mtime +30 -delete
|
# find "${INVENTORY_DIR}" -name "*.gz" -o -name "*.tar.gz" -mtime +30 -delete
|
||||||
else
|
else
|
||||||
echo "No old backup files found (older than 30 days)."
|
echo "No old backup files found (older than 30 days) in ${INVENTORY_DIR}."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== RESTORE INSTRUCTIONS ==="
|
echo "=== RESTORE INSTRUCTIONS ==="
|
||||||
echo "To restore from this backup:"
|
echo "To restore from this backup:"
|
||||||
echo "1. Database restore instructions: https://immich.app/docs/administration/backup-and-restore/#database"
|
echo "1. Database restore instructions: https://immich.app/docs/administration/backup-and-restore/#database"
|
||||||
echo "2. Upload directory: Extract ${UPLOAD_BACKUP_PATH} to your UPLOAD_LOCATION"
|
if [ "$COPY_SUCCESS" = true ]; then
|
||||||
|
echo "2. Upload directory: Extract ${SHARED_BACKUP_DIR}/$(basename "${UPLOAD_BACKUP_PATH}") to your UPLOAD_LOCATION"
|
||||||
|
echo ""
|
||||||
|
echo "Backup files are located in: ${SHARED_BACKUP_DIR}"
|
||||||
|
else
|
||||||
|
echo "2. Upload directory: Extract ${UPLOAD_BACKUP_PATH} to your UPLOAD_LOCATION"
|
||||||
|
echo ""
|
||||||
|
echo "Backup files are located in: ${BACKUP_DIR}"
|
||||||
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
echo "IMPORTANT: For a complete restore, you need BOTH the database backup AND the upload directory backup."
|
echo "IMPORTANT: For a complete restore, you need BOTH the database backup AND the upload directory backup."
|
||||||
echo "The database contains metadata, while the upload directory contains your actual photos and videos."
|
echo "The database contains metadata, while the upload directory contains your actual photos and videos."
|
||||||
|
|||||||
Reference in New Issue
Block a user