Skip to content
Holden Salomon edited this page Jun 13, 2026 · 11 revisions

Setup Guide

Prerequisites

  • Immich v1.106+ with face recognition enabled and people tagged
  • Frigate v0.16+ (face mode only)
  • Docker with the appropriate GPU runtime (optional but strongly recommended)

1. Get your Immich API key

  1. Open Immich → Account SettingsAPI Keys
  2. Click New API Key, give it a name (e.g. winnow), copy the key

2. Get your Frigate URL

This is the base URL of your Frigate instance, e.g. http://192.168.1.10:5000. Only needed for face mode — omit it entirely if you're using object mode.


3. Choose an image tag

Tag Arch Acceleration
:latest amd64 + arm64 NVIDIA CUDA 13.3 (amd64) · requires NVIDIA Container Toolkit
:rocm amd64 AMD ROCm · pass /dev/kfd + /dev/dri
:intel amd64 Intel Arc / iGPU via OpenVINO · pass /dev/dri, set OPENVINO_DEVICE=GPU
:cpu amd64 + arm64 CPU only · ~2 GB smaller · no GPU required

Use :cpu if your host has no supported GPU — it skips the entire GPU stack. Set a container memory limit of at least 2 GB (mem_limit: 2g) — the embedding models need roughly 1–1.5 GB.


4. Deploy with Docker Compose

Copy compose.yml and .env.example to a directory on your host:

mkdir winnow && cd winnow
curl -O https://raw.githubusercontent.com/sudolulo/winnow/main/compose.yml
curl -O https://raw.githubusercontent.com/sudolulo/winnow/main/.env.example
cp .env.example .env

Edit .env with your values:

IMMICH_URL=http://192.168.1.10:2283
API_KEY=your-immich-api-key
FRIGATE_URL=http://192.168.1.10:5000

Edit the volume paths in compose.yml to point to directories on your host where models, cache, and output crops should be stored:

volumes:
  - /your/path/to/models:/models
  - /your/path/to/cache:/app/.if_cache
  - /your/path/to/output:/app/frigate_train

These directories will be created automatically by Docker if they don't exist.

Start it:

docker compose up -d

Logs:

docker compose logs -f winnow

5. First run

On the first run, winnow downloads the embedding models (~1–2 GB) from HuggingFace and InsightFace. This happens once — subsequent runs use the cached models from your mounted volume and start immediately.


6. Scheduling

CRON_SCHEDULE controls both the run schedule and container lifetime:

CRON_SCHEDULE Behaviour
(unset) Run once on startup, then exit
(empty string) Stay alive; trigger manually with docker exec -it winnow winnow
Cron expression Run on startup, then repeat on schedule

Example — every Sunday at 3 AM:

CRON_SCHEDULE=0 3 * * 0

In scheduled mode the process (and loaded models) stays resident between runs, so each subsequent run starts immediately without re-loading models.


GPU passthrough

NVIDIA

Include the deploy block in your compose.yml (present in the example) and ensure the NVIDIA Container Toolkit is installed on your host:

deploy:
  resources:
    reservations:
      devices:
        - driver: nvidia
          count: all
          capabilities: [gpu]

Verify GPU access:

docker run --rm --gpus all nvidia/cuda:13.3.0-base-ubuntu22.04 nvidia-smi

AMD (ROCm)

Use image: ghcr.io/sudolulo/winnow:rocm and replace the deploy: block with:

devices:
  - /dev/kfd
  - /dev/dri
group_add:
  - video
  - render

Intel Arc / iGPU

Use image: ghcr.io/sudolulo/winnow:intel and replace the deploy: block with:

devices:
  - /dev/dri
group_add:
  - render
environment:
  - OPENVINO_DEVICE=GPU   # omit to run OpenVINO inference on CPU (default)

Set OPENVINO_DEVICE=GPU to target the Intel GPU. Omitting it (or setting CPU) runs OpenVINO on CPU — useful if you want Intel's optimised runtime without GPU passthrough.


Debugging

Set VERBOSE=true in your .env to enable DEBUG-level output on the console. The log file always captures DEBUG regardless of this setting:

# log file is written to the output volume (frigate_train mount)
docker exec winnow cat /app/frigate_train/winnow.log

Clone this wiki locally