Managing photos with self-hosted Immich

Managing photos with self-hosted Immich

·5 min read·Updated on February 24, 2026

Why self-host your photos

Family photos are probably the most valuable data anyone owns, and yet they're handed to Google Photos or iCloud without a second thought. The problem: free storage can shrink overnight, photos get compressed, and they may be used to train AI models.

Self-hosting on the NAS returns ownership of your data: no cloud storage cap, family sharing with no third party, full control.

Immich: the open-source Google Photos

Immich reproduces the essence of Google Photos: auto-backup from the phone, facial recognition, smart search, shared albums, a fluid timeline. The project is very active.

What sets it apart from Photoprism or LibrePhotos is the mobile apps: iOS and Android do background auto-backup exactly like Google Photos. That's what makes a family switch realistic — a near-identical experience, so zero friction.

Architecture and deployment

Immich is several services — the main server, PostgreSQL, and an ML service for facial recognition and semantic search — on an isolated photos_net Docker network.

# docker-compose.yml - Immich
services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    container_name: immich-server
    environment:
      - DB_HOSTNAME=immich-postgres
      - DB_USERNAME=immich
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_DATABASE_NAME=immich
      - IMMICH_MACHINE_LEARNING_URL=http://immich-ml:3003
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /mnt/data/photos/external:/usr/src/app/external
      - /etc/localtime:/etc/localtime:ro
    networks:
      - photos_net
    depends_on:
      - immich-postgres
      - immich-ml
    restart: unless-stopped

  immich-ml:
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    container_name: immich-ml
    volumes:
      - /mnt/data/apps/photos/ml-cache:/cache
    networks:
      - photos_net
    restart: unless-stopped

  immich-postgres:
    image: docker.io/tensorchord/pgvecto-rs:pg16-v0.2.0
    container_name: immich-postgres
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_USER=immich
      - POSTGRES_DB=immich
      - POSTGRES_INITDB_ARGS='--data-checksums'
    volumes:
      - /mnt/data/apps/photos/postgres:/var/lib/postgresql/data
    networks:
      - photos_net
    restart: unless-stopped

networks:
  photos_net:
    name: photos_net

The .env holds the sensitive variables:

# .env - Immich configuration
IMMICH_VERSION=release
DB_PASSWORD=a_strong_password_here
UPLOAD_LOCATION=/mnt/data/photos/upload

Web interface on port 2283, served in production through Caddy with automatic TLS.

Storage and external libraries

/mnt/data/
├── apps/photos/
│   ├── postgres/        # PostgreSQL database
│   └── ml-cache/        # ML model cache
└── photos/
    ├── upload/          # Photos uploaded via the app
    └── external/        # Imported libraries

External libraries are the key feature for a migration. With 50,000 photos already organised into folders (Family/Year/Event) on an old Synology, re-uploading everything through the mobile app isn't viable. You just mount the folder into the container and declare an external library.

Immich scans, indexes, extracts EXIF metadata, runs facial recognition and tagging. The photos appear in the timeline as if natively uploaded, and the original files stay where they are — zero duplication.

The AI features

  • Facial recognition: faces are detected and grouped automatically. Naming someone once is enough to surface all their photos.
  • Semantic search (CLIP): natural-language queries. "Beach sunset" returns the right photos even without tags, since the CLIP model understands visual content.
  • Object detection: automatic tagging of content (car, dog, mountain).

On an Intel N95 with no GPU, ML runs on CPU: expect 2-3 seconds per photo across all models, so several days of background processing for 50,000 photos. It's a one-off cost — afterwards, only new photos get processed, near-instantly.

The ML cache in /mnt/data/apps/photos/ml-cache avoids re-downloading 2 GB of models on every container restart.

Mobile app, SSO and backup

The Immich app (iOS and Android) does background auto-backup over Wi-Fi or mobile data, with an identical timeline, album sharing, and the same AI search capabilities as the web. Configuration is just the server URL, OIDC login and enabling backup; each user gets their own folder in /mnt/data/photos/upload.

Immich supports OIDC natively: with Authelia as the provider, every family member has their own account, photo space and albums, with sharing through shared albums.

For backups, photos live on a Btrfs RAID — a first layer of protection, but a RAID isn't a backup. On top of that: a daily PostgreSQL dump via cron (pg_dump, stored encrypted) and Btrfs snapshots of the photos with retention (7 daily, 4 weekly). Photos being immutable by nature, snapshots suffice; PostgreSQL needs a consistent dump.

Verdict

Immich gets close enough to the Google Photos experience to make a family transition frictionless, with full control over the data. External libraries make migrating from a Synology painless, and the AI features work remarkably well even on a modest CPU.

ShareLinkedInXBluesky

Related articles