LinuxcontainersTested on real hardware

Immich Photo Backup — Docker Compose Install

Deploy Immich v3 with Docker Compose on Linux. Downloads the official compose and env files, sets the upload location and database password, and starts the full stack on port 2283.

Distrosubuntu, debian, fedora, opensuse
Shellbash
Updated
Script
bash
#!/usr/bin/env bash
# Immich — self-hosted photo backup — Docker Compose install.
# Requires Docker + Compose plugin. See playbook: docker-install-linux.
# Official docs: https://immich.app/docs/install/docker-compose/
set -euo pipefail

UPLOAD_DIR="/tank/photos"  # change to your actual photo storage path
INSTALL_DIR="/opt/immich"

mkdir -p "${INSTALL_DIR}" "${UPLOAD_DIR}"
cd "${INSTALL_DIR}"

# Download the official compose + env files from the latest release
wget -O docker-compose.yml \
  https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env \
  https://github.com/immich-app/immich/releases/latest/download/example.env

# Patch the two values that must change before first start
sed -i "s|UPLOAD_LOCATION=.*|UPLOAD_LOCATION=${UPLOAD_DIR}|" .env

# Generate a random DB password and write it in
DB_PASS=$(openssl rand -hex 24)
sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${DB_PASS}|" .env

echo "DB password written to ${INSTALL_DIR}/.env"
echo "Upload location: ${UPLOAD_DIR}"
echo ""
echo "Starting Immich..."
docker compose up -d

echo ""
echo "Immich is starting. Allow ~60 s for the database to initialise."
echo "Web UI: http://$(hostname -I | awk '{print $1}'):2283"
echo ""
echo "First user created via the web UI becomes the admin."

What this does

Downloads Immich’s official docker-compose.yml and example.env directly from the project’s GitHub release (ensuring matching versions), patches the upload path and database password, and starts the stack. Uses openssl rand to generate a strong DB password automatically.

Immich v3.0.0 (released 2026-07-01) migrated to the VectorChord vector extension for PostgreSQL — the official compose file handles this automatically; no manual database setup is needed.

Why this approach

Immich is the self-hosted replacement for Google Photos or iCloud Photos — automatic mobile backup, facial recognition, map view, shared albums, and a clean mobile app, all running on hardware you own. For anyone who’s ever worried about a cloud provider changing pricing, losing photos in a service shutdown, or simply wanting their personal photo library to stay private, Immich makes the tradeoff concrete: more initial setup effort in exchange for no ongoing subscription and complete ownership of the data.

The reason to use Immich’s official docker-compose.yml rather than writing your own is that Immich is a multi-service stack — the main server, a separate machine-learning container for face recognition and CLIP embeddings, PostgreSQL with a vector extension, and Redis — and the services have specific version dependencies between them. The official compose file is versioned alongside the Immich release and pins all the right image tags. Using it as the base (downloaded from the release, not copy-pasted from a blog post that might be out of date) ensures everything is compatible.

Generating a strong database password with openssl rand -base64 32 rather than setting a memorable one is the right approach for a service you’re not logging into the database directly — only Immich needs the password, and it reads it from the environment file. A strong random password prevents a bruteforce attack on the database port if it’s ever inadvertently exposed. The same logic applies to the secret key: Immich uses it to sign tokens; a weak one weakens session security for every user.

Prerequisites

Services started

Container Role
immich-server Main API + web UI (port 2283)
immich-machine-learning Face recognition, CLIP search
immich-postgres PostgreSQL + VectorChord extension
redis Job queue cache

After install

  1. Open http://SERVER-IP:2283 — the first account you create is the administrator.
  2. Install the Immich iOS or Android app, point it at the same URL, and enable background backup.
  3. Back up .env (it holds the DB password): cp /opt/immich/.env /opt/immich/.env.bak

Upgrade Immich

cd /opt/immich
docker compose pull
docker compose up -d

Always read the release notes before a major version jump. For most users docker compose pull && up -d is the entire upgrade.

Change the upload location after install

Stop the stack, move the data, update .env, restart:

cd /opt/immich
docker compose down
mv /old/path /new/path
sed -i 's|UPLOAD_LOCATION=.*|UPLOAD_LOCATION=/new/path|' .env
docker compose up -d

Reach Immich remotely without opening ports

Install Tailscale on the server and your phone. The Immich mobile app works over Tailscale exactly as it does on the LAN — background auto-backup works on cellular.

Fedora / openSUSE notes

The script is distro-agnostic (wget, sed, openssl, docker compose) — works on any Linux host with Docker installed. On openSUSE, wget may need sudo zypper install -y wget.

Backup the database

# Dump the Immich PostgreSQL database to a file:
docker exec -t immich_postgres pg_dumpall -c -U postgres > immich_db_$(date +%Y%m%d).sql

Keep a copy of both the DB dump and the UPLOAD_LOCATION folder. The originals in UPLOAD_LOCATION are always the source of truth — the database is an index that can be rebuilt, but the original files cannot be recovered from the database alone.