Tutorials

Immich: Going Deeper

Chapter 13's photo library deployed step by step: a database password Immich will accept, proxy settings that survive large video uploads, the phone app, and moving between Immich versions safely.

intermediate ⏱ 60 min Be Your Own Cloud · Chapter 13 immichphotosbackup

· last updated 29 October 2026

Chapter 13 of Be Your Own Cloud explains Immich’s four containers and why the library lives on bulk storage. This page is the deploy in order, the proxy settings large uploads need, and how to handle Immich’s fast release pace without losing photos.

Folders and the password

mkdir -p /opt/stacks/immich
sudo mkdir -p /mnt/media/photos
cd /opt/stacks/immich

The .env from the book:

File /opt/stacks/immich/.env
# /opt/stacks/immich/.env
IMMICH_VERSION=v3.2.4
UPLOAD_LOCATION=/mnt/media/photos   # your photo library (Chapter 7)
DB_PASSWORD=a_long_random_password   # letters and numbers only
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
Exactly as printed in Be Your Own Cloud, Chapter 13 , p. 60 · all of Chapter 13's code

Immich’s database password must be letters and numbers only. Chapter 9’s openssl rand -base64 48 can produce +, / and =, so for this one password use hex instead — it’s only ever 0–9 and a–f:

openssl rand -hex 32

Put that value after DB_PASSWORD=, then chmod 600 .env.

Deploy it

The compose file, exactly as printed:

File /opt/stacks/immich/docker-compose.yml
services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION}
    container_name: immich_server
    restart: unless-stopped
    volumes:
      - ${UPLOAD_LOCATION}:/data   # your photo library -- set in .env
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    depends_on:
      - redis
      - database
    ports:
      - '2283:2283'
  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION}
    container_name: immich_machine_learning
    restart: unless-stopped
    volumes:
      - model-cache:/cache
    env_file:
      - .env
  redis:
    image: docker.io/valkey/valkey:9
    container_name: immich_redis
    restart: unless-stopped
  database:
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
    container_name: immich_postgres
    restart: unless-stopped
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_USER=${DB_USERNAME}
      - POSTGRES_DB=${DB_DATABASE_NAME}
      - POSTGRES_INITDB_ARGS=--data-checksums
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    shm_size: 128mb
volumes:
  model-cache:
Exactly as printed in Be Your Own Cloud, Chapter 13 , p. 59 · all of Chapter 13's code
docker compose up -d
docker compose logs -f immich-server

The first start downloads the images and sets up the database; give it a minute. Then open http://192.168.1.50:2283. The first account you create is the administrator — do it now, before anyone else on your network finds the page.

The proxy host

In Nginx Proxy Manager:

TabSettingValue
DetailsDomain Namesimmich.home.yourdomain.com
DetailsSchemehttp
DetailsForward Hostname / IP192.168.1.50
DetailsForward Port2283
DetailsWebsockets Supporton — the web app uses it for live updates
SSLSSL Certificateyour DNS-challenge certificate from Chapter 8
SSLForce SSL, HTTP/2 Supporton

Then add a local DNS record for immich.home.yourdomain.com in Pi-hole (or use the wildcard from the Pi-hole tutorial).

Chapter 13’s troubleshooting box warns about proxy timeouts on large uploads. The fix goes in the proxy host’s Advanced tab — in Nginx Proxy Manager 2.16 that’s the gear icon at the right-hand end of the tabs. These values are from Immich’s reverse-proxy documentation:

client_max_body_size 50000M;
proxy_request_buffering off;
client_body_buffer_size 1024k;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;

Finally, tell Immich its own address, so shared links point at the right place: Administration → Settings → Server Settings → External domain, https://immich.home.yourdomain.com.

The phone app

Install the Immich app, and for the server URL enter https://immich.home.yourdomain.com. Log in, choose which albums on the phone to back up, and turn on background backup. The first run uploads your whole camera roll, and the server’s machine-learning container will be busy for a while afterwards — Chapter 13 explains why that’s normal.

Moving between versions

Immich releases often, and some releases change the compose file or the database image. That’s why the book pins IMMICH_VERSION=v3.2.4 in .env and says to treat Immich’s own compose file as the source of truth when you deploy.

When you want a newer version:

  1. Read the release notes for every version between yours and the new one. Breaking changes are called out at the top.
  2. Compare the book’s compose file with the docker-compose.yml attached to the new release — especially the database image line. If it changed, change yours to match.
  3. Make sure last night’s backup ran (Chapter 18), then change IMMICH_VERSION in .env, docker compose pull, docker compose up -d.

Server and machine-learning always run the same version, because both read IMMICH_VERSION.

Backups

Chapter 18’s script takes a fresh pg_dump of Immich’s database before every backup and backs up the library in /mnt/media/photos. Immich also keeps its own nightly database dumps in a backups folder inside the library. Chapter 19’s database drill proves the dump restores — and it only works with the same database image that made the dump, which is one more reason to change versions deliberately.

Official documentation

Stuck on a step? Get in touch.