Skip to content

Immich — the photo library, its database, and the one trap in it

9,258 assets (2026-10-26). Four containers; data on the pool; DB dumped nightly. The originals are irreplaceable; the database is what makes them a library.

Why this shape

Originals are plain files under library/ and upload/ so every copy mechanism (parity, rsnapshot, precious) sees them as files. Albums, faces, favourites and edits exist only in Postgres, so the dump is copied everywhere the originals are.

Shape

  • Containers: immich-server (ghcr.io/immich-app/immich-server:${IMMICH_VERSION}, .env pins IMMICH_VERSION=v3 since 2026-10-26 so a pull never crosses a major version unseen), immich-machine-learning, immich-postgres (postgres:14-vectorchord0.4.3-pgvectors0.2.0), immich-redis (valkey 8). Compose config under ~/torrentvpn/immich/.
  • Data: /mnt/storage/immich/{library,upload,profile} originals · backups/ nightly dump immich-db-backup-<ts>-v<ver>-pg14.19.sql.gz at 02:00, 14 kept · thumbs/, encoded-video/ regenerable.
  • Postgres superuser is immich, not postgres (restore gotcha in ~/precious/RESTORE.txt).
  • Motion-photo trap: 13 Samsung motion photos have their only original as -MP.mp4 under encoded-video/. Any copy that excludes encoded-video/ as "regenerable" silently drops 13 originals. precious-sync.sh derives the list from the DB each run.
  • 34 files on disk with no DB row were SHA-1'd (09-02): all byte-identical duplicates of assets already in the library — leftovers of uploads Postgres correctly rejected. Harmless.

Upgrades

  • 2026-10-26 v2.4.1 → v3.3.5. Pre-checks that cleared it: DB already on vchord 0.4.3 (v3 drops pgvecto.rs), no removed env vars (*_PING_TIMEOUT, PRELOAD__CLIP, PRELOAD__FACIAL_RECOGNITION), OAuth off, CPU x86-64-v2, panel-photos uses only /albums, /search/metadata, /assets/{id}/thumbnail (still in v3). Postgres image digest unchanged. Migrations clean, 9,258 assets before and after, precious/history motion-photo query still returns 13.
  • Rollback: immich-server:rollback-v2.4.1 / immich-machine-learning:rollback-v2.4.1 local image tags + full pg_dumpall at /mnt/storage/immich/pre-v3-upgrade/immich-db-20261026-v2.4.1.sql.gz (DB migrations are one-way, so rollback = restore that dump, then run the old tags). .env.bak-20261026-immich-v3. Delete those once v3 has run clean for a couple of weeks.
  • Next major: read the release's breaking changes, pg_dumpall, bump IMMICH_VERSION, docker compose pull immich-server immich-machine-learning && docker compose up -d immich-server immich-machine-learning.

Connected to

If you change this

  • Hits: precious-sync (DB query + source paths) · rsnapshot excludes · the nightly dump timing vs precious-sync (02:00 → 02:20, keep that order) · docker-backup.sh skips the immich dir by name — data is on the pool, not in the config dir.
  • Does not hit: parity rules (all under an included tree) · other containers.

Surfaces

Surface Role
Immich app / web the users
docker exec immich-postgres psql -U immich the DB, read for verification
API key panel-photos (Angel, read-only: album.read/asset.read/asset.view), ~/.config/immich/env wall-panel screensaver reads the shared Screen Saver album (Angel + Yara editor)

See

  • Source: ~/torrentvpn/docker-compose.yml:438-500 · /usr/local/bin/precious-sync.sh:10-21