Zum Inhalt

Self-Hosting Photo Management: Immich on Debian Linux (Mobile Backup, CLIP Vector Search & HW Acceleration)

Executive Summary: Immich is the fastest-growing open-source self-hosted project for replacing Google Photos and Apple iCloud Photos. Built with a NestJS (TypeScript) backend, a dedicated Python Machine Learning (ONNX Runtime) microservice, Redis/Valkey job queues, and PostgreSQL with vector similarity indexing (pgvecto.rs / VectorChord), Immich delivers instant timeline scrubbing, background iOS/Android camera-roll auto-upload, local facial recognition, and natural-language CLIP semantic search (e.g., searching "sunset over mountains with a dog" across 100,000 photos completely offline).

  • Native iOS & Android Auto-Backup


    Back up Live Photos, ProRAW, and 4K60 videos automatically in the background whenever your phone connects to home Wi-Fi or WireGuard.

  • Offline CLIP Semantic Search


    Run ViT-B-32 / XLM-Roberta vision-language models locally via immich-machine-learning and query embeddings in PostgreSQL.

  • Facial Clustering & Memories


    Group family members automatically with local InsightFace detection, timeline "On This Day" memories, and shared partner albums.

  • Hardware Video & ML Acceleration


    Accelerate video transcoding (QSV/VA-API/NVENC) and ONNX ML inference using /dev/dri GPU device passthrough.


1. Immich Microservice Architecture

Immich separates interactive API requests from heavy asynchronous background tasks (thumbnail generation, video transcoding, and ONNX neural network inference) via Redis/Valkey queues:

%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
    APP["📱 Immich iOS / Android App<br/>& Web Timeline UI<br/>(HTTPS via Reverse Proxy)"]
    SRV["🚀 immich-server (NestJS)<br/>127.0.0.1:2283<br/>API + Background Workers"]
    REDIS["⚡ Valkey / Redis 7<br/>BullMQ Job Queue<br/>(Thumbnails & Transcode)"]
    ML["🧠 immich-machine-learning<br/>Python ONNX Runtime<br/>(CLIP + InsightFace)"]
    PG["🗄️ PostgreSQL + Vector Index<br/>Metadata + 512-Dim Vectors"]

    APP <--> SRV
    SRV <--> REDIS
    SRV <-->|"gRPC / HTTP Inference"| ML
    SRV <-->|"Vector Cosine Search"| PG

2. Production compose.yaml & .env Configuration on Debian

Store high-capacity photo/video uploads (UPLOAD_LOCATION) on your redundant storage array (ZFS / RAID1), while keeping the PostgreSQL vector database (DB_DATA_LOCATION) strictly on local NVMe SSD for sub-millisecond timeline scrolling:

# File: /srv/containers/immich/.env
IMMICH_VERSION=release
TZ=Europe/Berlin

# Large media library storage (NAS / RAID pool)
UPLOAD_LOCATION=/srv/media/immich-library

# Fast local NVMe SSD path for PostgreSQL vector index!
DB_DATA_LOCATION=/srv/containers/immich/postgres

DB_USERNAME=postgres
DB_DATABASE_NAME=immich
DB_PASSWORD=Replace_With_Strong_Alphanumeric_Password_2026
# File: /srv/containers/immich/compose.yaml
services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    depends_on:
      - redis
      - database
    restart: unless-stopped
    ports:
      - "127.0.0.1:2283:2283/tcp"
    env_file:
      - .env
    devices:
      - /dev/dri:/dev/dri
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload:rw
      - /etc/localtime:/etc/localtime:ro

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - /srv/containers/immich/model-cache:/cache:rw

  redis:
    container_name: immich_redis
    image: docker.io/valkey/valkey:8-bookworm
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "valkey-cli ping || exit 1"]

  database:
    container_name: immich_postgres
    image: docker.io/tensorchord/pgvecto-rs:pg16-v0.2.0
    restart: unless-stopped
    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:rw

3. Reverse Proxy Requirements (Large Video Upload Streaming!)

Mobile phones regularly upload 4K60 video files exceeding 2 GB–10 GB. If your reverse proxy (Nginx or Nginx Proxy Manager) enforces its default client_max_body_size 1m;, every video backup will fail with HTTP 413 Request Entity Too Large!

  • In Caddy: Unlimited request body size and WebSocket streaming work out of the box with zero extra directives (reverse_proxy 127.0.0.1:2283).
  • In Nginx / NPM: Explicitly configure:
# File: /etc/nginx/snippets/immich-proxy.conf
client_max_body_size 50000M;
proxy_read_timeout   600s;
proxy_send_timeout   600s;
send_timeout         600s;

4. Storage Template & External Library Best Practices

  1. Enable Storage Template: In Administration → Settings → Storage Template, enable the template engine ({{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}) so uploaded photos are organized cleanly on disk by year and date (2026/2026-11-06/IMG_4021.HEIC) rather than opaque UUID folders.
  2. External Libraries: If you also have an existing DSLR photo archive on disk, mount it into immich-server with :ro (Read-Only) and register it under Administration → External Libraries so Immich indexes it without moving or modifying the original files.

Where to Go Next

Pair Immich with off-site encrypted backups, WireGuard remote access, and Nextcloud file sync:

  • PhotoPrism RAW Archive Manager


    Compare Immich's mobile cloud focus with PhotoPrism's DSLR RAW and WebDAV archive workflow.

    PhotoPrism Guide

  • WireGuard VPN Server


    Keep Immich completely private off the public internet while auto-backing up photos from your phone via On-Demand WireGuard VPN.

    WireGuard Guide

  • BorgBackup + Borgmatic


    Automate daily deduplicated backups of /srv/media/immich-library and PostgreSQL dumps.

    BorgBackup Guide