Immich for the both of us

Immich for the both of us

Sep 01 ·
10 Min Read

There’s a shared folder on my Synology with my wife’s photos. Exports from services she no longer uses, dropped there when she left them and never looked at again. You can get to them fine. You open the folder, you scroll past thousands of files called IMG_2847 and you close it again. In practice nobody ever looks in there.

I’d had Immich running for months, only for myself. When I added that shared folder of my wife’s as an external library they suddenly became photos again. It became searchable all at once, sorted by date and with faces the system groups together on its own. The only thing missing was my wife who wants to access them.

So my wife got an account. That changed the question I was asking myself about Immich.

Until then the bar was low. If something broke I knew where to look. I don’t mind that self-hosting costs some maintenance now and then. The question wasn’t whether Immich works well enough for me, but whether it works well enough for someone who wants nothing to do with my homelab.

Why it’s here

Between us, Immich now manages around 125,000 photos and 15,000 videos here. There’s a second copy in there of what’s in iCloud, plus archives from services we once used that don’t exist anymore.

We still use iCloud Photos, after all. Immich isn’t a replacement, it sits alongside it.

Photos are probably the most personal set of data I have. There’s plenty in there we can’t make again. That’s exactly the kind of collection where I want to hold the original files myself. Not because I think Apple is going to throw them out tomorrow, but because I’d rather not have one party who gets to decide whether I can still reach them.

Backup is too big a word for what Immich does, by the way. It’s a second copy. The real backup sits underneath it, because the Synology backs itself up again to a second NAS somewhere else.

There is a question in the background about whether we could ever leave iCloud Photos. I don’t know the answer and I’m not in a hurry either, but I wanted to know how close it is. That’s not something you can work out on your own. A photo service that only works for the person running it isn’t a photo service, it’s a hobby project with a web interface.

Self-hosting isn’t a goal in itself for me either. If my wife needs help every week, then I’ve gained more control technically and put a worse product in the house.

The only measure that counts

For me, a container is allowed to fall over. For my wife, her photo just has to show up. So the measure became how often she has to ask me for help.

So far that’s been once. She asked for some explanation when she started. After that she sees a notification from the auto upload go by now and then. Otherwise she just uses it. She logs in with her password manager on an ordinary login screen. She doesn’t notice there’s a separate identity provider behind it.

What strikes me about that is that a notification like that is the only thing you can see of this whole setup. Everything below it, the VM and the identity provider and the rest, reaches her as a line on a lock screen saying photos have been uploaded. That’s how it should be. From the outside you never see how much sits underneath. That’s exactly how you know something is finished.

How it runs

Immich runs in a VM on Proxmox that does nothing else but Docker. The photos aren’t in that VM but on the Synology, which is mounted into the machine. In front of it sits Nginx Proxy Manager with its own domain and a certificate from Cloudflare. The domain sits behind the Cloudflare proxy as well.

If you just want to see how I’m running it, this is the whole Docker Compose.

name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
extends:
file: hwaccel.transcoding.yml
service: quicksync
env_file:
- .env
volumes:
- ${UPLOAD_LOCATION}:/data
- /mnt/synology-homes/<user>/Photos:/mnt/external-library:ro
- /etc/localtime:/etc/localtime:ro
ports:
- 2283:2283
depends_on:
- redis
- database
networks:
- default
- proxy
restart: always
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-openvino
extends:
file: hwaccel.ml.yml
service: openvino
env_file:
- .env
environment:
MACHINE_LEARNING_WORKER_TIMEOUT: "600"
MACHINE_LEARNING_WORKERS: "1"
MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION: "1"
MACHINE_LEARNING_MAX_BATCH_SIZE__OCR: "1"
volumes:
- model-cache:/cache
networks:
- default
restart: always
healthcheck:
disable: false
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
healthcheck:
test: redis-cli ping || exit 1
networks:
- default
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
networks:
- default
restart: always
healthcheck:
disable: false
volumes:
model-cache:
networks:
proxy:
external: true

A few lines in there say something about how I use Immich.

The mount with my wife’s photos is set to :ro. Immich can look inside it and change nothing.

The server has an Intel chip, so transcoding goes through Quick Sync and the machine learning through OpenVINO. Face recognition and making photos searchable therefore happen on the integrated GPU instead of on the processor.

That last part I did turn right down, to one worker and a batch size of one for both face recognition and OCR. With the default values the machine learning container kept crashing as soon as I threw that many photos at it at once. That’s the kind of problem you only get when you put years of archive through in one go, because in daily use nothing like that amount ever comes in at the same time. Once everything of my wife’s has been indexed I’ll put those values back up.

That’s also the only thing here that has genuinely broken. It happened on my side of the line. An indexing run that has to start over is my problem. For someone who opens her phone to look up a photo, nothing changes.

Beyond that the server sits on two networks. Its own network for Postgres and Valkey, plus an external network it shares with Nginx Proxy Manager. That proxy takes care of the domain and the certificate.

I could have put Immich behind Tailscale too, like almost everything here that’s only mine. I deliberately didn’t. The moment a VPN has to be on before a photo uploads, you’ve given the user something to think about again. An address that simply works on any network is the only version that can survive the test.

Logging in through Authentik

I don’t want to keep separate accounts and passwords for every self-hosted application, so everything here goes through Authentik as identity provider. Immich connects to it with OIDC.

For the user that produces an ordinary login screen. For me it produces an application that no longer stands on its own. If Authentik falls over, my wife can’t get to her photos even though Immich is running fine.

That’s the trade-off. It gets simpler for the people using it and more complicated for the person keeping it running. I chose that myself, but it’s the kind of dependency you don’t feel until the moment something goes wrong.

From a folder to a library

What Immich lays on top is the difference between a folder and a library. The photos end up on a timeline and faces get grouped together, so you can click a person and the rest appears by itself. Searching no longer goes by filename but by what’s in the picture.

That’s what the machine learning is running for. It’s also the reason I want this at home, because anyone who runs something like that over a complete photo collection knows a fair amount about someone’s life afterwards. That it happens here in a container on my own server saves me a lot of thinking.

That’s what happened to that old folder of my wife’s. Suddenly there’s a way in, which is why those photos exist again.

That it works this way comes down to the difference between importing and an external library. That difference is a big part of why Immich is here.

With an import, Immich takes the files over and puts them in its own storage structure. With an external library the files stay where they are and Immich only keeps an index on them. My wife’s folder is one of those. Those files are still on the Synology, in the same folders, with the same names. Immich isn’t even allowed to write there.

So if Immich stops existing tomorrow I don’t have a problem. I’d still have folders of photos on a disk that I can open with any viewer I like. That weighs heavier for me than the privacy story that usually comes with self-hosting. A cloud service can’t give you this.

The upgrade to 3

Immich 3 happened to come along in the middle of this. It’s a nice update, but for me it wasn’t the reason for anything. It was just the next one in line. I came from 2.7.5, which ran fine here. It was the first major update since someone else depended on it, though.

Two things could break. The vector database moved from pgvecto.rs to VectorChord. On top of that OAuth got stricter, because requests over plain http are now blocked and the issuer URL has to parse as a valid URL. That second one hits exactly the login my wife depends on. The full list of breaking changes is in Immich’s own migration post.

What I did do beforehand was read through the release notes, something I still skip now and then when it’s only me. An hour of downtime on a Saturday morning is an hour of tinkering for me. For someone who wants to look up a photo right then, it’s simply broken.

I also made a backup and then went in. The migration worked first time. Immich was down for about an hour, mostly because I was doing other things alongside it. I didn’t have to change anything about Authentik.

What it costs

Immich hasn’t been a standalone application here for a long time. There’s a proxy in front of it, Cloudflare in front of that, plus a login that goes through a separate service I run myself. Underneath it all is a Synology that passes its own copy on to a second NAS somewhere else. That’s the price of self-hosting and I pay it happily, only you shouldn’t pretend it’s zero.

Maintenance comes with it. Immich puts out updates regularly and I run those myself. The Synology has to stay healthy and there has to be someone who notices when the copy going offsite stops running. That’s me. There’s no second administrator here and no support department that takes over when I don’t feel like it for a week.

There’s something contradictory in it as well. I self-host to keep control while the traffic to my own photos runs through Cloudflare in the meantime. It’s the same trade-off I made with Tailscale, where I chose convenience over being fully in charge. I notice I make that trade-off more often than I would have expected.

The safety net

In the weeks my wife has been using Immich, nothing has broken that affected her. She asked for an explanation once and after that she uses it the way she uses any other app.

Only that says less than it seems. iCloud Photos is still sitting next to it. Every photo she sends to my server is also at Apple, so if that server goes up in smoke tonight she loses nothing. As long as that safety net is there, Immich has never really been under pressure here. That’s the difference between standing alongside and standing alone.

I do know what would have to happen before I take that safety net away. The auto upload would have to work as invisibly as Apple’s, including in a month where I don’t look at the server at all. And I’d have to accept that from that moment on, an outage on my server is an outage in our family.

Immich handles the first of those fine by now. Whether I’ll ever take that safety net away I don’t know yet. That I’m still hesitating about it is probably the most honest answer to the question I started with.

You might also like