Skip to content
appsgit

Deploy guide

How to self-host Immich with Docker Compose

Deploy Immich on any VPS or home server in 15 minutes: the official Docker Compose stack, .env settings, HTTPS reverse proxy, backups and safe upgrades.

  • Updated
  • Beginner
  • About 15 minutes

You will need

  • 2 vCPU / 4 GB RAM minimum (6 GB+ recommended)
  • Docker + Docker Compose v2
  • Disk space for your photo library on local storage
  • A domain name (optional, for HTTPS)

What is Immich?

Immich is a self-hosted photo and video backup platform that works as a private alternative to Google Photos and iCloud Photos. It is open source under the AGPL-3.0 license, has native mobile apps that back up your camera roll automatically, and includes face recognition, map view, shared albums and natural-language search. It is one of the most actively developed self-hosted projects on GitHub.

Requirements

  • A Linux server with at least 2 CPU cores and 4 GB of RAM (6 GB or more if you keep machine learning enabled).
  • Docker Engine and Docker Compose v2.
  • Local disk (SSD preferred) for the Postgres database, plus as much storage as your library needs.
  • A domain name pointing at the server if you want HTTPS access from your phone outside the house.

Step 1: Prepare the server

This guide assumes Ubuntu 24.04 with Docker already installed. If you still need Docker, follow the official Docker Engine install guide for Ubuntu and make sure docker compose version prints v2.

Create a working directory:

mkdir -p ~/immich && cd ~/immich

Step 2: Create the Docker Compose file

Immich ships its Compose file with every release, and the project warns that the file on the main branch may not match the latest release. The stack has four services: the server, the machine learning worker, Valkey (a Redis-compatible cache) and a custom Postgres image that bundles the VectorChord and pgvecto.rs extensions used for smart search.

Save this as docker-compose.yml:

name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - "2283:2283"
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      disable: false

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always
    healthcheck:
      disable: false

  redis:
    container_name: immich_redis
    image: docker.io/valkey/valkey:9
    healthcheck:
      test: redis-cli ping | grep -q PONG || exit 1
    restart: always

  database:
    container_name: immich_postgres
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.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:
      disable: false

volumes:
  model-cache:

Then create .env next to it:

UPLOAD_LOCATION=./library
DB_DATA_LOCATION=./postgres
TZ=Etc/UTC
IMMICH_VERSION=v3
DB_PASSWORD=CHANGE_ME
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Replace CHANGE_ME with a random value. Immich asks for letters and digits only in the database password, so a hex string is ideal: run openssl rand -hex 32 and paste the output. Pinning IMMICH_VERSION to a major version (v3) means you only move to the next major release when you choose to. For the most reproducible setup, download the exact file from the latest release instead of retyping it, because the official file also pins image digests.

Step 3: Start and open the app

docker compose up -d
docker compose ps

The first start downloads several gigabytes of images and machine learning models, so give it a few minutes. Then open http://YOUR_SERVER_IP:2283. The first account you create becomes the administrator. Install the Immich app on your phone, enter the server URL, sign in, and enable background backup.

Step 4: Put it behind HTTPS

The mobile apps work best over HTTPS on a real domain. With Caddy installed on the host, this is the whole config:

photos.example.com {
    reverse_proxy 127.0.0.1:2283
}

Caddy fetches a Let's Encrypt certificate automatically. Immich uploads can be large, and Caddy has no body size limit by default. If you use Nginx Proxy Manager instead, raise client_max_body_size and enable WebSocket support. Once HTTPS works, change the port mapping to "127.0.0.1:2283:2283" so the plain HTTP port is no longer reachable from the internet. Docker-published ports bypass ufw.

Backups and upgrades

Back up two things: the UPLOAD_LOCATION folder (your originals, thumbnails and encoded videos) and the database. Immich creates automatic database dumps inside UPLOAD_LOCATION/backups, so copying the whole library folder off-site with a tool like restic or Borg covers both. Never copy the raw postgres folder while the container is running.

To upgrade, read the release notes first (Immich occasionally has breaking changes), then run:

docker compose pull && docker compose up -d

Troubleshooting

  • Server keeps restarting after an upgrade: you are probably running an old docker-compose.yml against a new image. Download the Compose file from the matching release and compare.
  • Face recognition or smart search never finishes: the machine learning container may be out of memory. Check docker compose logs immich-machine-learning, and add RAM or swap.
  • Uploads fail through the reverse proxy: raise the proxy's upload size limit and timeouts. Large videos can exceed common defaults.
  • Database errors on a NAS: move DB_DATA_LOCATION to local disk. Network shares are not supported for Postgres.

Next steps

Set up external libraries to index existing photo folders without copying them, enable the storage template to control folder naming, and create user accounts for your family. If you have a supported GPU, add the hardware acceleration Compose files for faster transcoding and machine learning.

Spotted something out of date? Tell us and we will update the guide.

FAQ

Immich questions

Still curious? Email info@appsgit.com.

What port does Immich use?

The Immich server listens on port 2283. The mobile apps and the web UI both connect to that port, or to your HTTPS domain once you put a reverse proxy in front of it.

Is Immich free?

Yes. Immich is free and open source under the AGPL-3.0 license. There is an optional paid supporter license that unlocks nothing; it only funds development.

How much RAM does Immich need?

The project recommends at least 4 GB, and 6 GB or more for comfortable machine learning (face recognition and smart search). On small servers you can disable the machine learning container to save memory.

Does Immich need a GPU?

No. The default Compose file runs transcoding and machine learning on the CPU. Hardware acceleration for NVIDIA, Intel, AMD and some ARM boards is optional and enabled through extra Compose files.

Immich vs PhotoPrism: which should I choose?

Immich is closer to a Google Photos replacement, with native iOS and Android apps and automatic phone backup. PhotoPrism focuses on browsing, tagging and organising an existing library through the browser.

Can I store the Immich database on a NAS share?

No. The Postgres data directory must be on local storage, because network shares are not supported for the database. The photo library itself can live on a NAS mount.