The first thing I installed on my new home server was a photo management app. Not because I had a perfectly thought-out plan. I just wanted to see if this was even possible, and photos were the whole point of starting.
I ended up testing two: Immich and PhotoPrism. Both are open source Google Photos alternatives. Both run in Docker. I figured I’d try them side by side and see which one I preferred.
First impressions: running both at once#
Getting both up was straightforward enough. Docker Compose files, a few environment variables, done. I installed the Immich mobile app on my phone, pointed it at the server, and started backing up. Watching the photos appear on the server in real time was a good moment.
Then the server slowed to a crawl.
Immich does AI processing in the background: face recognition, object detection, generating embeddings for smart search. PhotoPrism does similar things. Running both at the same time on a 2013 laptop CPU was too much. CPU hit 100% and stayed there. I just left it running, though I was impatient the whole time because I had a list of other things I wanted to set up and couldn’t do anything until this settled.
It also became clear pretty quickly that the two apps overlapped too much to bother running both. I went with Immich — it’s more actively developed and has a proper Android app. The processing took longer than I expected too, partly because the library kept growing as I added more photos through the cleanup process I’ll get to shortly. But more on that later.
The storage situation I hadn’t thought through#
At this point, Immich had my phone photos, about two years’ worth that I’d just backed up directly. But I had a bigger problem I’d been ignoring.
My actual photo library was split across two places:
- Koofr: a 1TB lifetime account with about two years of photos backed up there
- Google Photos: everything else, including older photos and, awkwardly, the same last two years that were also in Koofr
So I had duplicates, I had photos in Google that weren’t anywhere else, and I’d just added a third copy of recent photos in Immich’s local storage. It was a mess.
The right solution was to get everything out of Google, merge it all, clean it up, and put it in one place. Which sounds simple. It is not simple.
Google Takeout: the first circle of hell#
Google lets you export all your Photos data through a service called Google Takeout. You request an export, they prepare it, you download it. In theory. In practice, Google treats your own data like a hostage negotiation.
My library was large enough that it split into multiple zip files. The export took time to prepare. Downloading everything was slow. And when I extracted it all, I had a folder full of photos where roughly half of them had their metadata (dates, locations, descriptions) stored in separate .json sidecar files instead of embedded in the image itself.
This is a known Google Photos quirk and it is genuinely annoying. The photos and their metadata are separate files, named in a way that’s sometimes obvious and sometimes not. If you just copy the photos and ignore the sidecar files, you end up with images where the date is wrong or missing entirely, which messes up your timeline.
Fixing the metadata: the second circle of hell#
There’s a tool called exiftool that can read the sidecar .json files and write the metadata back into the images. There’s also a Python script that automates this across an entire Takeout folder. I used one I found after some searching.
The process works, but it takes time and you need to be careful about running it on the right folders in the right order. I ran it, spot-checked a bunch of files, and eventually had a photo library where the dates looked right.
Then I uploaded everything to Koofr.
The duplicate problem#
Now I had:
- The old Koofr photos (two years of backups)
- The Google Takeout photos (everything, including those same two years)
- Some overlap with the phone photos already in Immich
Koofr has a built-in duplicate detection tool. It found duplicates across the library and let me review and remove them. It took a few passes but eventually I got down to one clean copy of everything.
This part wasn’t painful exactly. It was just slow and required attention. But it felt good when it was done.
The better approach: external library#
After going through all of that, I discovered something I wish I’d known from the start: Immich supports external libraries.
Instead of uploading photos into Immich’s own storage, you can point it at a folder and tell it to treat that as a read-only library. It scans the photos, does all the AI processing, builds the face recognition and search index, but doesn’t move or copy the files. The originals stay wherever they are.
This was one of those moments where everything clicks. I’d been thinking about this wrong the whole time.
Now:
- The actual photo files live in Koofr (mounted on the server via rclone)
- Immich scans that mounted folder as an external library
- Immich handles all the AI/ML: faces, smart search, timeline
- Backing up means backing up to Koofr, not managing a separate Immich library
The photos have one authoritative home. Immich is the interface and intelligence layer on top.
The backup picture#
The actual files live in Koofr, which covers the offsite copy. I sync to an external hard drive occasionally for a local copy:
rsync -av --progress /media/koofr/photos/ /media/external/photos/I do back up the Immich database separately, so if the server dies the face tags, albums, and metadata are all recoverable. The photos are in Koofr, the database is backed up. Starting over would just be a restore, not a rescan.
Where things stand#
Immich is running, photos are there, everything is searchable and organised.
The process of getting here was messier than I expected. The Takeout export, the metadata fixing, the duplicates. But it was a one-time effort. Everything going forward is clean: phone backs up to Immich, Immich reads from Koofr, Koofr is the source of truth.
If you’re considering doing the same thing, my advice: start the Google Takeout export early, expect the metadata process to take time, and set up the external library from day one rather than importing into Immich directly.
