replacing google photos with immich - self-hosted photo backup with face recognition
Immich is a self-hosted Google Photos alternative with automatic iPhone backup, face recognition, and semantic search. here's how it's set up on a homelab mini PC and how 6,700+ photos got migrated from Google Takeout.
why replace google photos with immich
Google Photos is convenient until it isn't - storage limits, privacy concerns, or just wanting to own your data. Immich replicates the Google Photos experience on your own hardware. face grouping, album organization, map view, and "search by what's in the photo" all work - no cloud subscription required.
the stack
Immich isn't a single container. it runs four:
immich-server— main app and APIimmich-machine-learning— face recognition and CLIP image embeddingsimmich-database— Postgres with thepgvecto.rsextension (vector search for CLIP)immich-redis— job queue cache
the ML container uses CUDA on the RTX 3070. face clustering and semantic search are significantly faster with GPU acceleration than on CPU.
importing from google photos
Google Takeout exports photos as a mix of tgz archives with JSON sidecar files containing metadata — timestamps, GPS coordinates, album membership. the sidecars matter: without them, every photo shows the export date instead of when it was actually taken.
immich-go handles the import correctly:
# extract the takeout archives first
mkdir ~/takeout-extracted
tar -xzf ~/Downloads/takeout-*.tgz -C ~/takeout-extracted
# upload with metadata preserved
immich-go upload from-google-photos --no-ui \
--server=http://10.0.3.21:2283 \
--api-key=YOUR_KEY \
~/takeout-extracted
the --no-ui flag is required — the TUI breaks in some terminal environments. point it at the extracted folder, not the tgz directly.
immich-go reads the JSON sidecars, sets correct dates and GPS data, and preserves album structure. it deduplicates by file hash, so running it multiple times or mixing with iPhone backups doesn't create duplicates.
iphone backup
the Immich iOS app connects directly to the local server and backs up the camera roll in the background, exactly like Google Photos. new photos sync automatically on the same network. deduplication handles the overlap with Takeout imports.
the ml jobs
after import, Immich queues background jobs for every photo: thumbnail generation, face detection, CLIP embedding. these run through the ML container. with CUDA, a library of 6,700 photos finishes in under an hour. without GPU it takes significantly longer.
once done, the face grouping UI shows clusters of recognized faces to name, and the search bar understands queries like "beach sunset" or "birthday cake" without any manual tagging.
gotchas
don't enable storage template before importing. the storage template feature renames and reorganizes files on disk. enabling it before the initial import means immich-go can't match incoming files to already-imported ones by path, and you'll get duplicates.
immich needs its own Postgres. the pgvecto.rs extension required for vector search isn't available in standard Postgres images. immich ships its own Postgres image (ghcr.io/immich-app/postgres) that includes it. it can't share the homelab's shared Postgres instance.
hardware for self-hosted photo storage
Immich needs two things: storage space for photos and some compute for the ML jobs. a mini PC with 16-32GB RAM handles the server, database, and ML processing. for photo storage, a NAS drive or external USB drive works - the photos just need to be on a reliable filesystem that Docker can mount. the GPU acceleration is nice for initial import but not required - Immich works fine on CPU, just slower for the initial face recognition pass.

AMD Ryzen - compact, fanless, low power
Runs Immich, face recognition, and photo backup from home
view on amazonaffiliate link - helps support the blog
eli5
imagine moving your entire photo collection out of a rented storage unit (Google Photos) and into a room in your house. the room has all the same features — automatic labeling, face grouping, search by what's in the picture — except it runs on your hardware and nobody else has a key. the moving truck (immich-go) reads the labels Google put on every box (JSON sidecars) so nothing ends up mislabeled or in the wrong album. once everything is moved in, a very fast assistant (the GPU) goes through every photo and builds an index so you can find anything instantly.