What you will set up
Immich backs up the photos and videos from your phone and shows them in a timeline, on a map and in albums you can share. It recognises faces, and it can search by what is in a picture: type a dog on a beach, and it finds it. The phone apps upload new pictures by themselves.
Here it runs as a pod under a user of its own called immich, behind Caddy from the Podman guide: the Immich server, its machine learning, PostgreSQL and Valkey. The photos stay on your server, in a folder you can back up.
Every step below was run on a Melonslab server with Debian 13:
- Immich 3.2.2 was set up, and two photos were uploaded through its API, the way the phone apps upload.
- Thumbnails were made, and a search for
a dogput the dog first, anda catthe cat. - Everything came back by itself after a reboot, with the search still working.
The pod used about 2.2 GB of memory, over half of it for machine learning. Immich asks for at least 6 GB on the server, and recommends 8 GB. With 4 GB, it runs with machine learning turned off. The photos take the space they take, so check your server's disk before you move a large library.
Before you start
You need:
- a server set up as in the Podman guide, with Caddy running, and at least 6 GB of memory;
- an A record and an AAAA record for
photos.example.compointing at your server.
The examples use photos.example.com for Immich and 203.0.113.10 for your server's IPv4 address, which ip -brief address show eth0 shows. Replace them throughout.
1. Create the user
As root:
useradd -m -s /bin/bash immich
loginctl enable-linger immich
machinectl shell immich@
Everything up to step 4 runs as immich.
2. Create the database password
openssl rand -hex 24 | tr -d '\n' | podman secret create immich-db-password -
3. Describe the pod
mkdir -p ~/.config/containers/systemd ~/immich/library
cd ~/.config/containers/systemd
Your photos go in ~/immich/library. Create immich.pod:
[Pod]
PodName=immich
# Only Caddy, on this server, can reach Immich: the port is not open to the internet.
PublishPort=127.0.0.1:8098:2283
ShmSize=128m
[Install]
WantedBy=default.target
Create immich-db.container:
[Container]
ContainerName=immich-db
Image=ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
Pod=immich.pod
Volume=immich-db:/var/lib/postgresql/data
Environment=POSTGRES_USER=postgres POSTGRES_DB=immich POSTGRES_INITDB_ARGS=--data-checksums
Secret=immich-db-password,type=env,target=POSTGRES_PASSWORD
[Service]
Restart=always
Create immich-redis.container:
[Container]
ContainerName=immich-redis
Image=docker.io/valkey/valkey:9
Pod=immich.pod
AutoUpdate=registry
[Service]
Restart=always
Create immich-ml.container:
[Container]
ContainerName=immich-ml
Image=ghcr.io/immich-app/immich-machine-learning:v3
Pod=immich.pod
Volume=immich-model-cache:/cache
AutoUpdate=registry
[Service]
Restart=always
And immich-server.container:
[Unit]
After=immich-db.service immich-redis.service
[Container]
ContainerName=immich-server
Image=ghcr.io/immich-app/immich-server:v3
Pod=immich.pod
Volume=%h/immich/library:/data
Environment=DB_HOSTNAME=127.0.0.1 DB_USERNAME=postgres DB_DATABASE_NAME=immich
Environment=REDIS_HOSTNAME=127.0.0.1 IMMICH_MACHINE_LEARNING_URL=http://127.0.0.1:3003
Environment=TZ=Europe/Stockholm
# Caddy's connections reach the pod from the server's own IPv4 address.
Environment=IMMICH_TRUSTED_PROXIES=203.0.113.10
Secret=immich-db-password,type=env,target=DB_PASSWORD
AutoUpdate=registry
[Service]
Restart=always
The database is Immich's own build of PostgreSQL, with the extensions its search needs, and it stays on the version Immich's own setup names. The v3 tag keeps Immich on its newest 3.x release. TZ is the time zone Immich shows times in.
Start it:
systemctl --user daemon-reload
systemctl --user start immich-pod
systemctl --user enable --now podman-auto-update.timer
The first start downloads the images, which take about 3.6 GB of disk, and takes a few minutes.
4. Put Caddy in front
Go back to root with exit, switch to machinectl shell caddy@, and add this block at the end of ~/Caddyfile:
photos.example.com {
reverse_proxy 127.0.0.1:8098
}
Restart Caddy with systemctl --user restart caddy. Caddy passes uploads of any size, so large videos go through too.
5. Set it up
Open https://photos.example.com, and choose Getting Started. Create the admin account, with Admin Email, Admin Password, Confirm Admin Password and Name, and log in. Immich then walks you through a few settings. Two of them are about outside services:
- Server Privacy: Map loads map tiles from
tiles.immich.cloud, and Version Check asksversion.immich.cloudfor new releases. Both are on. Turn them off if you want Immich not to contact anyone. - User Privacy: Google Cast loads resources from Google. It is off, and this guide leaves it off.
Every setting can be changed later, under Administration and Settings.
To give someone else an account, open Administration, Users, and choose Create user. Immich has no open sign-up page.
6. Upload from your phone
Install Immich's app for Android or iPhone. Enter https://photos.example.com as the server, log in, and turn on backup for the albums you want. New photos then go to your server by themselves. On a computer, drag photos into the web page.
The first time Immich processes photos, its machine-learning container downloads its models, about 800 MB: from Hugging Face, and the model that reads text in pictures from ModelScope. Only the models are downloaded. Your photos never leave your server.
7. Back up
Everything worth keeping is in ~/immich/library: the photos and videos as they were uploaded, and, in its backups folder, a copy of the database that Immich makes every night at 02:00, keeping the last 14. Copy the whole folder to another machine regularly, for example with rsync.
To make a copy of the database right now, as immich:
mkdir -p ~/backup
podman exec immich-db pg_dumpall --clean --if-exists -U postgres | gzip > ~/backup/immich-db.sql.gz
Troubleshooting
Search finds nothing, or faces are not recognised. Machine learning runs in the background, after thumbnails. Administration, Job Queues shows what is waiting. The first run also waits for the models to download.
The page does not load after an update. Read podman logs immich-server. A new Immich release sometimes needs a new database image: its release notes say so, and name the new tag for immich-db.container.