From 710c28aae02848dc4b54c4721ced7d7ecaa2fd48 Mon Sep 17 00:00:00 2001 From: j Date: Thu, 15 Jan 2026 11:28:49 +1300 Subject: [PATCH] Add 26 files --- immich/_volumes.sh | 9 ++++ immich/backup.sh | 36 +++++++++++++++ immich/config/service.env | 32 +++++++++++++ immich/destroy.sh | 25 ++++++++++ immich/docker-compose.yml.template | 73 ++++++++++++++++++++++++++++++ immich/install.sh | 42 +++++++++++++++++ immich/logs.sh | 12 +++++ immich/restore.sh | 21 +++++++++ immich/start.sh | 14 ++++++ immich/status.sh | 13 ++++++ immich/stop.sh | 16 +++++++ immich/template_info.env | 8 ++++ immich/uninstall.sh | 18 ++++++++ 13 files changed, 319 insertions(+) create mode 100755 immich/_volumes.sh create mode 100755 immich/backup.sh create mode 100644 immich/config/service.env create mode 100755 immich/destroy.sh create mode 100644 immich/docker-compose.yml.template create mode 100755 immich/install.sh create mode 100755 immich/logs.sh create mode 100755 immich/restore.sh create mode 100755 immich/start.sh create mode 100755 immich/status.sh create mode 100755 immich/stop.sh create mode 100644 immich/template_info.env create mode 100755 immich/uninstall.sh diff --git a/immich/_volumes.sh b/immich/_volumes.sh new file mode 100755 index 0000000..ccb420f --- /dev/null +++ b/immich/_volumes.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Define volume items for immich +# These are used across backup, restore, create, and destroy operations + +get_immich_volumes() { + echo "path:uploads:${UPLOAD_LOCATION}" + echo "path:database:${DB_DATA_LOCATION}" + echo "volume:model_cache:${CONTAINER_NAME}_model_cache" +} diff --git a/immich/backup.sh b/immich/backup.sh new file mode 100755 index 0000000..2062f38 --- /dev/null +++ b/immich/backup.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/_volumes.sh" + +_check_required_env_vars "CONTAINER_NAME" "BACKUP_FILE" "TEMP_DIR" "UPLOAD_LOCATION" "DB_DATA_LOCATION" "DB_USERNAME" + +echo "Backing up ${CONTAINER_NAME}..." + +cd "$SCRIPT_DIR" || _die "Failed to change to script directory" + +[ -f docker-compose.yml ] || _die "docker-compose.yml not found." + +# Dump the database before backup +echo "Dumping PostgreSQL database..." +docker exec "${CONTAINER_NAME}_postgres" pg_dumpall -U "${DB_USERNAME}" > "${TEMP_DIR}/database.sql" \ + || _die "Failed to dump database" + +# Copy the dump to the DB data location for inclusion in backup +cp "${TEMP_DIR}/database.sql" "${DB_DATA_LOCATION}/database_backup.sql" + +# Stop containers for consistent backup +docker compose stop + +# Backup volumes +# shellcheck disable=SC2046 +backup_items $(get_immich_volumes) || _die "Failed to create backup" + +# Restart containers +docker compose start + +# Clean up +rm -f "${DB_DATA_LOCATION}/database_backup.sql" + +echo "Backup complete: ${BACKUP_FILE}" diff --git a/immich/config/service.env b/immich/config/service.env new file mode 100644 index 0000000..b49ba92 --- /dev/null +++ b/immich/config/service.env @@ -0,0 +1,32 @@ +# Immich - Self-hosted photo and video management +# https://github.com/immich-app/immich + +# Server Settings +SSH_USER="dropshell" + +# Container name prefix (containers will be named immich_server, immich_redis, etc.) +CONTAINER_NAME=immich + +# Immich version - use "release" for latest stable +IMMICH_VERSION=release + +# Web UI port +WEB_PORT=2283 + +# Upload location - where photos/videos are stored +UPLOAD_LOCATION=/path/to/uploads + +# Database settings +DB_DATA_LOCATION=/path/to/postgres +DB_PASSWORD=change_me_to_a_secure_password +DB_USERNAME=postgres +DB_DATABASE_NAME=immich + +# Optional: Additional read-only media library paths (comma-separated) +# These will be mounted as read-only in the immich-server container +# Example: "/mnt/photos:/photos:ro,/mnt/archive:/archive:ro" +EXTERNAL_LIBRARIES="" + +# Machine Learning settings +# For GPU acceleration, change to: release-cuda, release-openvino, or release-armnn +ML_IMAGE_TAG=release diff --git a/immich/destroy.sh b/immich/destroy.sh new file mode 100755 index 0000000..d330eab --- /dev/null +++ b/immich/destroy.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/_volumes.sh" + +_check_required_env_vars "CONTAINER_NAME" + +echo "WARNING: This will PERMANENTLY DELETE all data for ${CONTAINER_NAME}" + +cd "$SCRIPT_DIR" || _die "Failed to change to script directory" + +# Stop and remove containers and volumes +if [ -f docker-compose.yml ]; then + docker compose down -v 2>/dev/null || true +fi + +# Destroy data directories +# shellcheck disable=SC2046 +destroy_items $(get_immich_volumes) || _die "Failed to destroy volumes" + +# Remove generated compose file +rm -f docker-compose.yml + +echo "Destroyed ${CONTAINER_NAME} and all associated data." diff --git a/immich/docker-compose.yml.template b/immich/docker-compose.yml.template new file mode 100644 index 0000000..32b67a5 --- /dev/null +++ b/immich/docker-compose.yml.template @@ -0,0 +1,73 @@ +name: ${CONTAINER_NAME} + +services: + immich-server: + container_name: ${CONTAINER_NAME}_server + image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release} + volumes: + - ${UPLOAD_LOCATION}:/usr/src/app/upload + - /etc/localtime:/etc/localtime:ro + environment: + - DB_PASSWORD=${DB_PASSWORD} + - DB_USERNAME=${DB_USERNAME} + - DB_DATABASE_NAME=${DB_DATABASE_NAME} + - DB_HOSTNAME=${CONTAINER_NAME}_postgres + - REDIS_HOSTNAME=${CONTAINER_NAME}_redis + ports: + - '${WEB_PORT:-2283}:2283' + depends_on: + - redis + - database + restart: unless-stopped + healthcheck: + disable: false + + immich-machine-learning: + container_name: ${CONTAINER_NAME}_machine_learning + image: ghcr.io/immich-app/immich-machine-learning:${ML_IMAGE_TAG:-release} + volumes: + - ${CONTAINER_NAME}_model_cache:/cache + environment: + - DB_PASSWORD=${DB_PASSWORD} + - DB_USERNAME=${DB_USERNAME} + - DB_DATABASE_NAME=${DB_DATABASE_NAME} + - DB_HOSTNAME=${CONTAINER_NAME}_postgres + - REDIS_HOSTNAME=${CONTAINER_NAME}_redis + restart: unless-stopped + healthcheck: + disable: false + + redis: + container_name: ${CONTAINER_NAME}_redis + image: docker.io/redis:6.2-alpine + healthcheck: + test: redis-cli ping || exit 1 + restart: unless-stopped + + database: + container_name: ${CONTAINER_NAME}_postgres + image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0 + environment: + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_USER: ${DB_USERNAME} + POSTGRES_DB: ${DB_DATABASE_NAME} + POSTGRES_INITDB_ARGS: '--data-checksums' + volumes: + - ${DB_DATA_LOCATION}:/var/lib/postgresql/data + healthcheck: + test: pg_isready --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' || exit 1 + interval: 5m + command: + [ + 'postgres', + '-c', 'shared_preload_libraries=vectors.so', + '-c', 'search_path="$$user", public, vectors', + '-c', 'logging_collector=on', + '-c', 'max_wal_size=2GB', + '-c', 'shared_buffers=512MB', + '-c', 'wal_compression=on', + ] + restart: unless-stopped + +volumes: + ${CONTAINER_NAME}_model_cache: diff --git a/immich/install.sh b/immich/install.sh new file mode 100755 index 0000000..58c5ddf --- /dev/null +++ b/immich/install.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/_volumes.sh" + +_check_required_env_vars "CONTAINER_NAME" "UPLOAD_LOCATION" "DB_DATA_LOCATION" "DB_PASSWORD" + +# Set defaults +IMMICH_VERSION="${IMMICH_VERSION:-release}" +ML_IMAGE_TAG="${ML_IMAGE_TAG:-release}" +WEB_PORT="${WEB_PORT:-2283}" +DB_USERNAME="${DB_USERNAME:-postgres}" +DB_DATABASE_NAME="${DB_DATABASE_NAME:-immich}" + +# Export all variables for envsubst +export CONTAINER_NAME UPLOAD_LOCATION DB_DATA_LOCATION DB_PASSWORD DB_USERNAME DB_DATABASE_NAME +export WEB_PORT IMMICH_VERSION ML_IMAGE_TAG + +cd "$SCRIPT_DIR" || _die "Failed to change to script directory" + +# Generate docker-compose.yml from template +echo "Generating docker-compose.yml..." +envsubst < docker-compose.yml.template > docker-compose.yml \ + || _die "Failed to generate docker-compose.yml" + +# Create data directories +_create_folder "${UPLOAD_LOCATION}" +_create_folder "${DB_DATA_LOCATION}" + +# Pull images +echo "Pulling Immich images..." +docker compose pull || _die "Failed to pull images" + +# Stop and remove existing containers +bash ./stop.sh 2>/dev/null || true + +# Start services +bash ./start.sh || _die "Failed to start containers" + +echo "Installation complete for ${CONTAINER_NAME}." +echo "Web UI available at http://localhost:${WEB_PORT}" diff --git a/immich/logs.sh b/immich/logs.sh new file mode 100755 index 0000000..84836c3 --- /dev/null +++ b/immich/logs.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +_check_required_env_vars "CONTAINER_NAME" + +cd "$SCRIPT_DIR" || _die "Failed to change to script directory" + +[ -f docker-compose.yml ] || _die "docker-compose.yml not found." + +docker compose logs -f diff --git a/immich/restore.sh b/immich/restore.sh new file mode 100755 index 0000000..c98f341 --- /dev/null +++ b/immich/restore.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/_volumes.sh" + +_check_required_env_vars "CONTAINER_NAME" "BACKUP_FILE" "TEMP_DIR" "UPLOAD_LOCATION" "DB_DATA_LOCATION" + +echo "Restoring ${CONTAINER_NAME} from backup..." + +# Uninstall before restore +bash ./uninstall.sh || _die "Failed to uninstall service before restore" + +# Restore volumes from backup +# shellcheck disable=SC2046 +restore_items $(get_immich_volumes) || _die "Failed to restore from backup" + +# Reinstall service +bash ./install.sh || _die "Failed to reinstall service after restore" + +echo "Restore complete! Service ${CONTAINER_NAME} is running." diff --git a/immich/start.sh b/immich/start.sh new file mode 100755 index 0000000..d537d85 --- /dev/null +++ b/immich/start.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +_check_required_env_vars "CONTAINER_NAME" + +cd "$SCRIPT_DIR" || _die "Failed to change to script directory" + +[ -f docker-compose.yml ] || _die "docker-compose.yml not found. Run install.sh first." + +docker compose up -d || _die "Failed to start containers" + +echo "Immich containers started successfully." diff --git a/immich/status.sh b/immich/status.sh new file mode 100755 index 0000000..2624306 --- /dev/null +++ b/immich/status.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" + +_check_required_env_vars "CONTAINER_NAME" + +# Check if main server container is running +if ! _is_container_running "${CONTAINER_NAME}_server"; then + _die "Service is not running - container ${CONTAINER_NAME}_server not found or stopped." +fi + +echo "Service is healthy" +exit 0 diff --git a/immich/stop.sh b/immich/stop.sh new file mode 100755 index 0000000..9bdd8d6 --- /dev/null +++ b/immich/stop.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +_check_required_env_vars "CONTAINER_NAME" + +echo "Stopping ${CONTAINER_NAME}..." + +cd "$SCRIPT_DIR" || _die "Failed to change to script directory" + +[ -f docker-compose.yml ] || _die "docker-compose.yml not found." + +docker compose stop || _die "Failed to stop containers" + +echo "Immich containers stopped." diff --git a/immich/template_info.env b/immich/template_info.env new file mode 100644 index 0000000..fa9f93f --- /dev/null +++ b/immich/template_info.env @@ -0,0 +1,8 @@ +# Template info - AUTO GENERATED, DO NOT EDIT +TEMPLATE=immich +REQUIRES_HOST_ROOT=false +REQUIRES_DOCKER=true +REQUIRES_DOCKER_ROOT=true + +# Default container name prefix +CONTAINER_NAME=immich diff --git a/immich/uninstall.sh b/immich/uninstall.sh new file mode 100755 index 0000000..4472b47 --- /dev/null +++ b/immich/uninstall.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# shellcheck disable=SC1091 +source "${AGENT_PATH}/common.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +_check_required_env_vars "CONTAINER_NAME" + +echo "Uninstalling ${CONTAINER_NAME}..." + +cd "$SCRIPT_DIR" || _die "Failed to change to script directory" + +# Stop and remove containers (preserves volumes) +if [ -f docker-compose.yml ]; then + docker compose down 2>/dev/null || true +fi + +echo "Uninstallation of ${CONTAINER_NAME} complete." +echo "Data preserved in upload and database locations."