# 05-immich.md

kstack:
  book: Centerpoint Home Lab
  chapter: Media & Entertainment
  page: Immich
  tags: [immich, photos, media, cuda, gpu, self-hosted]
---

## Overview

Immich is the self-hosted photo and video library for the homelab — a local
alternative to Google Photos. It provides automatic mobile backup, face recognition,
smart search, and album management. The machine learning container runs on the RTX
5080 via CUDA for accelerated facial recognition and CLIP-based smart search.

Photo storage lives on the UnRAID NAS NFS mount at `/mnt/Photos`.

## Access

| Type      | URL                                 | Notes                                                 |
|-----------|-------------------------------------|-------------------------------------------------------|
| Internal  | `https://photos.home.local`         | LAN access via Step-CA TLS                            |
| External  | `https://photos.jeevesconsults.ca`  | GeoBlock (CA/US/IN) + CrowdSec — no Authentik ForwardAuth |

Immich uses its own user authentication — Authentik ForwardAuth is not applied
because it would break the mobile app OAuth flow.

## Containers in This Stack

| Container                 | Image                                                              | GPU | Role                              |
|---------------------------|--------------------------------------------------------------------|-----|-----------------------------------|
| `immich_server`           | `ghcr.io/immich-app/immich-server:release`                         | No  | Main API and web server           |
| `immich_machine_learning` | `ghcr.io/immich-app/immich-machine-learning:release-cuda`          | Yes | Face recognition + CLIP search    |
| `immich_postgres`         | `ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0`  | No  | PostgreSQL with pgvecto.rs        |
| `immich_redis`            | `valkey/valkey:8-bookworm`                                         | No  | Job queue and cache               |

## Configuration

**Compose file:** `/home/jeeves/docker/immich/docker-compose.yml`
**Compose project:** `immich`

### Ports

| Port   | Protocol | Purpose                              |
|--------|----------|--------------------------------------|
| `2283` | TCP      | Immich web UI and API (host-bound)   |

### Traefik Labels

```yaml
# External route
traefik.http.routers.immich.rule: Host(`photos.jeevesconsults.ca`)
traefik.http.routers.immich.entrypoints: websecure
traefik.http.routers.immich.tls.certresolver: letsencrypt
traefik.http.routers.immich.middlewares: plex-geoblock@file,crowdsec-bouncer@file,immich-headers
traefik.http.middlewares.immich-headers.headers.customrequestheaders.X-Forwarded-Proto: https

# Internal route
traefik.http.routers.immich-internal.rule: Host(`photos.home.local`)
traefik.http.routers.immich-internal.entrypoints: websecure
traefik.http.routers.immich-internal.tls.certresolver: step-ca

traefik.http.services.immich.loadbalancer.server.port: 2283
```

### Key Environment Variables (`.env` file)

| Variable               | Value / Notes                                          |
|------------------------|--------------------------------------------------------|
| `UPLOAD_LOCATION`      | `/mnt/Photos/immich-library`                           |
| `DB_HOSTNAME`          | `immich_postgres`                                      |
| `DB_USERNAME`          | `postgres`                                             |
| `DB_PASSWORD`          | **REDACTED**                                           |
| `DB_DATABASE_NAME`     | `immich`                                               |
| `REDIS_HOSTNAME`       | `immich_redis`                                         |
| `TZ`                   | `America/Toronto`                                      |
| `IMMICH_VERSION`       | `release` (pinned to latest stable)                    |

## Volumes / Bind Mounts

| Host Path / Volume                        | Container Path              | Purpose                              |
|-------------------------------------------|-----------------------------|--------------------------------------|
| `/mnt/Photos/immich-library`              | `/data`                     | Primary upload library (NFS)         |
| `/mnt/Photos/Plex`                        | `/mnt/Photos/Plex:rw`       | Plex photo library (external library)|
| `/mnt/Photos/Google_Photos`               | `/mnt/Photos/Google_Photos:rw` | Google Photos import folder       |
| `/etc/localtime`                          | `/etc/localtime:ro`         | Host timezone sync                   |
| `model-cache` (named volume)              | `/cache`                    | ML model weight cache (machine learning container) |
| `${DB_DATA_LOCATION}` (from .env)         | `/var/lib/postgresql/data`  | PostgreSQL data                      |

### Sub-section: Machine Learning (CUDA)

`immich_machine_learning` runs with `runtime: nvidia`, giving it access to the RTX
5080 for:

- **Face detection and recognition** — identifies and clusters faces across the library
- **CLIP embeddings** — powers smart search ("photos of dogs at the beach")

| Environment Variable         | Value | Purpose                              |
|------------------------------|-------|--------------------------------------|
| `NVIDIA_VISIBLE_DEVICES`     | `all` | GPU access                           |
| `NVIDIA_DRIVER_CAPABILITIES` | `compute,utility` | CUDA compute caps        |
| `MACHINE_LEARNING_DEVICE_ID` | `0`   | Use GPU device 0                     |

ML model files are cached in the `model-cache` named Docker volume. Models are
downloaded from HuggingFace on first use and cached for subsequent runs.

### Sub-section: PostgreSQL (pgvecto.rs)

Immich uses a custom PostgreSQL 14 image with the `pgvecto.rs` and `pgvectors`
extensions pre-installed. These extensions power the vector similarity search that
underlies CLIP smart search and face clustering.

```
ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
```

The `shm_size: 128mb` allocation is required for PostgreSQL's shared memory.

### Sub-section: Redis / Valkey

`immich_redis` uses Valkey (the Redis fork) as the job queue and cache backend.
It handles background job scheduling for ML processing, thumbnail generation, and
library scans.

## Dependencies

- NFS mounts `/mnt/Photos` (UnRAID) must be healthy
- `immich_postgres` → `immich_redis` → `immich_server` startup order
- NVIDIA container runtime for `immich_machine_learning`

## Notes / Gotchas

- Immich does not use Authentik ForwardAuth — it has built-in multi-user auth.
  The mobile app connects directly to `https://photos.jeevesconsults.ca`.
- The `X-Forwarded-Proto: https` header (`immich-headers` middleware) is required
  for Immich to generate correct share links and OAuth callbacks.
- The PostgreSQL image is pinned to a specific digest — do not change it
  arbitrarily. Immich releases are tied to specific database schema versions.
- Library scan and ML job processing can be CPU/GPU intensive. Schedule large
  library scans during off-peak hours via Admin → Jobs.
- External libraries (Plex photos, Google Photos) are read-only imports. Changes
  to files in these directories are picked up on the next library scan.

---
*Last Updated: 2026-06-16*