DockerHomeLab
A rack of networked server hardware
guides

Self-Host Immich (Photos) with Docker Compose

Replace Google Photos with Immich, a self-hosted photo and video backup server. The official Docker Compose stack, the .env file, mobile auto-backup, hardware acceleration, and reverse-proxy notes.

By Editorial · · 8 min read

Immich is the self-hosted photo and video manager that finally makes leaving Google Photos realistic. It has polished iOS and Android apps with automatic background backup of your camera roll, a fast timeline, albums, sharing, map view, and local machine learning for face recognition and natural-language search (“show me photos of my dog at the beach”). All of it runs on your hardware, and your photos never touch a third party’s servers.

Immich is more involved than a single-container service — it ships as a small stack of containers — but the project maintains an official Docker Compose file that does the heavy lifting. This guide installs that official stack, explains each piece, sets up mobile backup, and covers hardware acceleration and reverse proxying.

One caveat worth knowing up front: Immich is under very active development and the project officially notes that things can change between releases. Pin a version, read the release notes before upgrading, and — most importantly — keep good backups. This is non-negotiable for irreplaceable photos.

What’s in the Stack

The official Compose file defines four services. It’s worth knowing what each does:

  • immich-server — the main application: web UI, API, and the backup endpoint the mobile apps talk to. It publishes port 2283.
  • immich-machine-learning — runs the ML models for face recognition and CLIP-based smart search. Separated so you can give it more resources or hardware acceleration independently.
  • redis (a Valkey image) — in-memory store for job queues and caching.
  • database — a PostgreSQL image built by the Immich team with the VectorChord/pgvector extensions that power similarity search. Immich requires this specific image; a stock Postgres will not work.

You don’t write these service definitions by hand — you download them from the project.

Prerequisites

  • Docker and Docker Compose installed
  • A directory with plenty of space for your photo library (this only grows)
  • Enough RAM that the ML container is comfortable — 4 GB total is a workable floor, 8 GB+ is better once your library is large

Step 1: Download the Official Compose File and Env Template

Make a directory and pull the two files Immich publishes with each release:

mkdir -p ~/services/immich
cd ~/services/immich

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

These are the exact commands from Immich’s official documentation. Downloading the maintained file (rather than copy-pasting a snippet from a blog) is the right call here: the stack’s service images and wiring change over time, and the released file is always internally consistent.

Step 2: Configure the .env File

Open .env and set the key variables. The ones that matter:

# Where your uploaded photos and videos are stored on the host
UPLOAD_LOCATION=./library

# Where the Postgres database files live on the host
DB_DATA_LOCATION=./postgres

# Your timezone, e.g. America/New_York
TZ=America/New_York

# Pin a specific version instead of tracking "release"
IMMICH_VERSION=release

# Database credentials — change the password to something random
DB_PASSWORD=postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Two pieces of advice:

  • Change DB_PASSWORD to a long random string before first launch. Changing it later means migrating the database, which is a hassle.
  • Pin IMMICH_VERSION to a specific release tag (for example v2.7.5) rather than leaving it on release. That way an up -d doesn’t silently jump major versions — you upgrade deliberately, after reading the release notes.

UPLOAD_LOCATION is the most important setting: it’s the directory holding every photo you back up. Put it on a disk with room to grow, and put it in your backup plan.

Step 3: Start the Stack

From ~/services/immich:

docker compose up -d

Docker pulls four images (server, machine learning, the Valkey cache, and the Immich Postgres image) and starts them in order. The first start takes a few minutes while the database initializes. Watch progress with:

docker compose logs -f immich-server

When the server is ready, open http://your-server-ip:2283. You’ll get the admin registration page — the first account you create is the administrator. Create it, log in, and you’re looking at an empty timeline ready for photos.

Step 4: Set Up Mobile Auto-Backup

This is the feature that replaces Google Photos.

  1. Install Immich from the App Store or Google Play.
  2. On the login screen, enter your server URL. On your local network that’s http://your-server-ip:2283; once you’ve set up a reverse proxy (next section), use the HTTPS domain.
  3. Log in with the account you created.
  4. Open the app’s backup settings, select the albums to back up (usually your Camera Roll), and enable background backup.

The app uploads in the background and tracks which assets are already backed up, so it’s safe to let it run. To migrate your existing Google Photos library, use Google Takeout to export, then upload the export through the web UI or the immich-cli bulk uploader.

Step 5: Hardware Acceleration (Optional but Worth It)

Two parts of Immich benefit from hardware acceleration:

  • Machine learning (face recognition, smart search) can use a GPU or other accelerator on the immich-machine-learning container.
  • Video transcoding can use a GPU on the server container.

Immich ships separate hardware-acceleration Compose override files for this. Download the one matching your hardware alongside the main file — for example the machine-learning override:

wget -O hwaccel.ml.yml https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml

Then enable the relevant profile per Immich’s hardware-acceleration documentation (the exact section depends on whether you have Intel QuickSync, NVIDIA, or another accelerator). On CPU-only hardware Immich still works — ML jobs simply run slower, which is fine for a personal library that indexes once and then keeps up incrementally.

Step 6: Reverse Proxy for HTTPS and Remote Access

To use Immich from outside your network, and to let the mobile app connect over HTTPS, put it behind a reverse proxy pointed at the server container’s port 2283. With Traefik, you add labels to the immich-server service in the downloaded Compose file:

  immich-server:
    # ...existing config from the official file...
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.immich.rule=Host(`photos.yourdomain.com`)"
      - "traefik.http.routers.immich.entrypoints=websecure"
      - "traefik.http.routers.immich.tls.certresolver=letsencrypt"
      - "traefik.http.services.immich.loadbalancer.server.port=2283"
    networks:
      - traefik-proxy

Add the external traefik-proxy network to the file’s networks: block so the server can join it. Photo and video uploads can be large, so make sure your proxy doesn’t impose a small request-size limit — Traefik has no default body-size cap, but if you use Nginx Proxy Manager, raise client_max_body_size in the advanced config.

Because your entire photo history is sensitive, the same advice as other services applies: if you don’t need public access, exposing Immich only over a VPN (WireGuard or Tailscale) is the safer posture. The mobile app connects to a private hostname just as happily as a public one.

Step 7: Backups — The Part You Cannot Skip

Immich is photo storage. Treat it like the irreplaceable data it is. A complete backup is two things:

  1. The upload library — your UPLOAD_LOCATION directory. These are the actual files.
  2. The database — your faces, albums, metadata, and the mapping that makes the library navigable. Dump it with pg_dump from the database container on a schedule.

A library backup without the database leaves you with a folder of files and no organization; a database backup without the files leaves you with metadata pointing at nothing. You need both. Apply a real 3-2-1 backup strategy here above any other service — the cost of getting it wrong is your family photos.

Step 8: Updating

Because you pinned IMMICH_VERSION, upgrading is deliberate:

  1. Read the release notes for the version you’re moving to (Immich calls out breaking changes there).
  2. Make sure your backup just ran.
  3. Bump IMMICH_VERSION in .env to the new tag.
  4. Re-pull and recreate:
docker compose pull
docker compose up -d

The database migrations run automatically on start. Following the release notes and keeping the version pinned is what keeps Immich’s fast pace of development from surprising you.

The Result

You’ve replaced Google Photos with a faster, private, ad-free timeline that does face recognition and smart search locally, backs up your phone automatically, and stores everything on disks you own. It’s the single most compelling self-hosted swap for most people — and the one where good backups matter most. For the wider context of moving off Google’s stack, see the self-hosted Google Photos alternatives comparison.

Sources

  1. Immich — Docker Compose installation (official docs)
  2. Immich — Hardware-Accelerated Machine Learning

Related

Comments