Files
docker/immich/backup_immich_db.sh

148 lines
5.1 KiB
Bash
Executable File

#!/bin/bash
# Immich Postgres Database Backup Script
# This script creates a # Check if the Postgres container exists and is running
echo "Checking postgres container status..."
if ! docker ps -q --filter "name=immich_postgres" | grep -q .; then
echo "Error: immich_postgres container is not running. Cannot proceed with backup."
exit 1
fi
echo "Taking database backup using pg_dumpall as recommended by Immich documentation..."
# Use pg_dumpall with recommended flags: --clean and --if-exists
docker exec -t immich_postgres pg_dumpall \
--clean \
--if-exists \
--username="${DB_USERNAME}" \
> "${BACKUP_PATH}" 2>/tmp/pg_dumpall_error.log
# Check if the dump was successful the Immich Postgres database
# Based on recommendations from https://immich.app/docs/administration/backup-and-restore/
# Set up error handling
set -e
# Function to ensure server is unpaused even if script fails
cleanup() {
local exit_code=$?
echo "Running cleanup..."
# Check if immich_server is paused and unpause it if needed
if [ "${IMMICH_SERVER_RUNNING:-true}" = true ] && docker inspect --format='{{.State.Status}}' immich_server 2>/dev/null | grep -q "paused"; then
echo "Unpausing immich_server container during cleanup..."
docker unpause immich_server 2>/dev/null || true
fi
if [ $exit_code -ne 0 ]; then
echo "Script failed with exit code $exit_code"
fi
exit $exit_code
}
# Set up trap to call cleanup function on script exit (normal or error)
trap cleanup EXIT SIGINT SIGTERM
# Load environment variables from the .env file
ENV_FILE="$(dirname "$0")/.env"
if [ -f "$ENV_FILE" ]; then
echo "Loading environment variables from $ENV_FILE"
source "$ENV_FILE"
else
echo "Error: .env file not found in $(dirname "$0")"
exit 1
fi
# Verify required environment variables are set
if [ -z "$DB_USERNAME" ] || [ -z "$DB_DATABASE_NAME" ]; then
echo "Error: Required environment variables (DB_USERNAME, DB_DATABASE_NAME) not found in .env file"
exit 1
fi
# Initialize container status variables
IMMICH_SERVER_RUNNING=true
# Create backup directory if it doesn't exist
BACKUP_DIR="$(dirname "$0")/database_backups"
mkdir -p "$BACKUP_DIR"
# Generate timestamp for the backup filename
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILENAME="immich_db_backup_${TIMESTAMP}.sql"
BACKUP_PATH="${BACKUP_DIR}/${BACKUP_FILENAME}"
echo "Starting backup of Immich Postgres database..."
echo "Using database settings from .env file:"
echo " - Database: ${DB_DATABASE_NAME}"
echo " - Username: ${DB_USERNAME}"
echo " - Container: immich_postgres"
# Check if the Immich server container exists and is running
echo "Checking immich_server container status..."
if docker ps -q --filter "name=immich_server" | grep -q .; then
echo "Pausing immich_server container to minimize database writes..."
if ! docker pause immich_server; then
echo "Failed to pause immich_server container."
# Continue with backup instead of exiting
fi
else
echo "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 "Taking database backup using pg_dumpall as recommended by Immich documentation..."
# Use pg_dumpall with recommended flags: --clean and --if-exists
docker exec -t immich_postgres pg_dumpall \
--clean \
--if-exists \
--username="${DB_USERNAME}" \
> "${BACKUP_PATH}"
# Check if the dump was successful
if [ $? -ne 0 ] || [ ! -s "${BACKUP_PATH}" ]; then
echo "Error: Database backup failed or created an empty file."
if [ -f "/tmp/pg_dumpall_error.log" ]; then
echo "Error details:"
cat /tmp/pg_dumpall_error.log
rm /tmp/pg_dumpall_error.log
fi
exit 1
fi
# Clean up error log if it exists
rm -f /tmp/pg_dumpall_error.log
# Compress the backup file
echo "Compressing backup file..."
if ! gzip -f "${BACKUP_PATH}"; then
echo "Warning: Failed to compress backup file."
fi
# Resume the Immich server only if it was running and we paused it
if [ "${IMMICH_SERVER_RUNNING:-true}" = true ]; then
echo "Resuming immich_server container..."
if ! docker unpause immich_server 2>/dev/null; then
echo "Note: No need to unpause immich_server container."
fi
fi
echo "Backup completed successfully!"
echo "Backup saved to: ${BACKUP_PATH}.gz"
# Optional: List backups and show total size
echo -e "\nBackup information:"
find "${BACKUP_DIR}" -name "*.gz" | wc -l | xargs echo "Total number of backups:"
du -sh "${BACKUP_DIR}" | cut -f1 | xargs echo "Total backup size:"
# Optional: Check if backup file is smaller than expected (potential warning)
BACKUP_SIZE=$(du -k "${BACKUP_PATH}.gz" | cut -f1)
if [ ${BACKUP_SIZE} -lt 100 ]; then
echo "Warning: Backup file is smaller than expected (${BACKUP_SIZE}KB). Please verify its integrity."
fi
# Optional: Remove backups older than 30 days
# find "${BACKUP_DIR}" -name "immich_db_backup_*.sql.gz" -mtime +30 -delete
echo -e "\nTo restore this backup, follow the instructions at: https://immich.app/docs/administration/backup-and-restore/"