Skip to content

Immich

Docker Compose deployment guide for Immich on Ubuntu.

Immich is a self-hosted photo and video management platform that provides automatic backups, facial recognition, machine learning features, timeline browsing, albums, sharing, and mobile app support.

Official project:


Why Use Immich?

Many homelab users use Immich as a private alternative to Google Photos.

Key features include:

  • Automatic photo and video uploads
  • Facial recognition
  • Object and location search
  • Shared albums
  • Mobile applications for Android and iPhone
  • Machine learning features
  • External library support
  • Self-hosted and privacy focused

Create the Project Folder

mkdir -p ~/docker/immich
cd ~/docker/immich

Create the Environment File

Create:

nano .env

Paste:

UPLOAD_LOCATION=./library
DB_DATA_LOCATION=./postgres

DB_PASSWORD=change_this_password
DB_USERNAME=immich
DB_DATABASE_NAME=immich

IMMICH_VERSION=release

Save and exit.


Create the Docker Compose File

Create:

nano docker-compose.yml

Paste:

services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:release
    container_name: immich_server
    restart: unless-stopped

    ports:
      - "2283:2283"

    volumes:
      - ./library:/usr/src/app/upload

    env_file:
      - .env

    depends_on:
      - redis
      - database

  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:release
    container_name: immich_machine_learning
    restart: unless-stopped

    volumes:
      - model-cache:/cache

    env_file:
      - .env

  redis:
    image: valkey/valkey:7
    container_name: immich_redis
    restart: unless-stopped

  database:
    image: tensorchord/pgvecto-rs:pg16-v0.2.0
    container_name: immich_postgres
    restart: unless-stopped

    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}

    volumes:
      - ./postgres:/var/lib/postgresql/data

volumes:
  model-cache:

Start Immich

Run:

docker compose up -d

Verify the containers are running:

docker ps

Access Immich

Open:

http://YOUR_SERVER_IP:2283

Example:

http://192.168.1.100:2283

First Login

When accessing Immich for the first time:

  1. Create the administrator account
  2. Log in using your new credentials
  3. Install the Immich mobile application
  4. Configure automatic photo backups

Storage Locations

This guide stores data in:

~/docker/immich
├── docker-compose.yml
├── .env
├── library
└── postgres

The folders contain:

Folder Purpose
library Uploaded photos and videos
postgres Database files

Reverse Proxy Recommendation

For remote access, a reverse proxy is strongly recommended.

Benefits include:

  • HTTPS encryption
  • Easier access using a domain name
  • Automatic certificate management
  • Better security

Example:

https://photos.yourdomain.com

If you are new to reverse proxies, see the Topic page:

What is a Reverse Proxy?


Notes

  • Immich works best with a large storage location for photos and videos
  • Mobile apps are available for Android and iPhone
  • Machine learning features may take time to process large photo libraries
  • Database backups are recommended
  • Reverse proxy and HTTPS are recommended for remote access

Advanced Example (Reference Only)

This is my current Immich deployment.

It includes:

  • External media library support
  • Machine learning health checks
  • Additional PostgreSQL tuning
  • Separate data locations
  • Graceful shutdown timers
name: immich

services:
  immich-server:
    container_name: immich_server
    stop_grace_period: 90s
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}

    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - ${EXTERNAL_PATH}:/mnt/media/photos:ro
      - /etc/localtime:/etc/localtime:ro

    env_file:
      - .env

    ports:
      - "2283:2283"

    depends_on:
      - redis
      - database

    restart: always

  immich-machine-learning:
    container_name: immich_machine_learning
    stop_grace_period: 90s
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}

    volumes:
      - model-cache:/cache

    env_file:
      - .env

    restart: always

    healthcheck:
      test: ["CMD-SHELL", "python3 -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:3003/ping\")' || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  redis:
    container_name: immich_redis
    stop_grace_period: 90s
    image: docker.io/valkey/valkey:7

    restart: always

    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      interval: 10s
      timeout: 5s
      retries: 5

  database:
    container_name: immich_postgres
    stop_grace_period: 90s
    image: tensorchord/pgvecto-rs:pg16-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

    shm_size: 128mb

    restart: always

    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  model-cache: