Skip to content

Immich Machine Learning Immich Machine Learning

Description / nameInput element
Container Registry
Container Configuration Root Path
Timezone
User ID
Group ID
Immich Machine Learning Host Port
Immich Machine Learning /cache Path
Immich Machine Learning /config Path

Build Status Last Commit

Machine learning service for Immich — handles facial recognition, image classification, and semantic search using ONNX models.

Port 3003
Registry ghcr.io/daemonless/immich-ml
Daemonless daemonless/immich-ml
Source immich-app/immich
Website immich.app

Version Tags

Tag Description Best For
latest Upstream Binary. Built from official release. Most users — recommended.

Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions, including the security model for host vs. container privileges.

Deployment

services:
  immich-ml:
    image: "ghcr.io/daemonless/immich-ml:latest"
    container_name: immich-ml
    environment:
      - MACHINE_LEARNING_HOST=0.0.0.0  # Host to bind to (0.0.0.0)
      - MACHINE_LEARNING_PORT=3003  # Port to bind to (3003)
      - MACHINE_LEARNING_CACHE_FOLDER=/cache  # Path to cache folder (/cache)
      - PUID=1000  # User ID for the application process
      - PGID=1000  # Group ID for the application process
      - TZ=UTC  # Timezone for the container
      - MACHINE_LEARNING_WORKERS=1  # Number of ML worker processes. Keep at 1 on weak / CPU-only hosts.
      - MACHINE_LEARNING_WORKER_TIMEOUT=300  # Gunicorn worker timeout in seconds. Raise on slow CPUs so model loading doesn't time out and cycle the worker.
      - SKIP_CHOWN=true  # Skip the one-time recursive chown of /cache and /config once ownership is recorded in /config/.chown_done (default true). Set false to force a chown on every start.
    volumes:
      - "/path/to/containers/immich-ml/cache:/cache"
      - "/path/to/containers/immich-ml:/config"
    ports:
      - "3003:3003"
    # always (not unless-stopped) so FreeBSD's podman rc.d auto-starts it at boot
    restart: always
podman run -d --name immich-ml \
  -p 3003:3003 \
  -e MACHINE_LEARNING_HOST=0.0.0.0 \
  -e MACHINE_LEARNING_PORT=3003 \
  -e MACHINE_LEARNING_CACHE_FOLDER=/cache \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=UTC \
  -e MACHINE_LEARNING_WORKERS=1 \
  -e MACHINE_LEARNING_WORKER_TIMEOUT=300 \
  -e SKIP_CHOWN=true \
  -v /path/to/containers/immich-ml/cache:/cache \
  -v /path/to/containers/immich-ml:/config \
  ghcr.io/daemonless/immich-ml:latest
- name: Deploy immich-ml
  containers.podman.podman_container:
    name: immich-ml
    image: "ghcr.io/daemonless/immich-ml:latest"
    state: started
    restart_policy: always
    env:
      MACHINE_LEARNING_HOST: "0.0.0.0"
      MACHINE_LEARNING_PORT: "3003"
      MACHINE_LEARNING_CACHE_FOLDER: "/cache"
      PUID: "1000"
      PGID: "1000"
      TZ: "UTC"
      MACHINE_LEARNING_WORKERS: "1"
      MACHINE_LEARNING_WORKER_TIMEOUT: "300"
      SKIP_CHOWN: "true"
    ports:
      - "3003:3003"
    volumes:
      - "/path/to/containers/immich-ml/cache:/cache"
      - "/path/to/containers/immich-ml:/config"
# .env

DIRECTOR_PROJECT=immich-ml
MACHINE_LEARNING_HOST=0.0.0.0
MACHINE_LEARNING_PORT=3003
MACHINE_LEARNING_CACHE_FOLDER=/cache
PUID=1000
PGID=1000
TZ=UTC
MACHINE_LEARNING_WORKERS=1
MACHINE_LEARNING_WORKER_TIMEOUT=300
SKIP_CHOWN=true
# appjail-director.yml

options:
  - virtualnet: ':<random> default'
  - nat:
services:
  immich-ml:
    name: immich_ml
    options:
      - container: 'boot args:--pull'
      - expose: '3003:3003 proto:tcp'
    oci:
      user: root
      environment:
        - MACHINE_LEARNING_HOST: !ENV '${MACHINE_LEARNING_HOST}'
        - MACHINE_LEARNING_PORT: !ENV '${MACHINE_LEARNING_PORT}'
        - MACHINE_LEARNING_CACHE_FOLDER: !ENV '${MACHINE_LEARNING_CACHE_FOLDER}'
        - PUID: !ENV '${PUID}'
        - PGID: !ENV '${PGID}'
        - TZ: !ENV '${TZ}'
        - MACHINE_LEARNING_WORKERS: !ENV '${MACHINE_LEARNING_WORKERS}'
        - MACHINE_LEARNING_WORKER_TIMEOUT: !ENV '${MACHINE_LEARNING_WORKER_TIMEOUT}'
        - SKIP_CHOWN: !ENV '${SKIP_CHOWN}'
    volumes:
      - IMMICH_ML_CACHE_PATH: /cache
      - IMMICH_ML_CONFIG_PATH: /config
volumes:
  IMMICH_ML_CACHE_PATH:
    device: '/path/to/containers/immich-ml/cache'
  IMMICH_ML_CONFIG_PATH:
    device: '/path/to/containers/immich-ml'
1
2
3
4
5
6
# Makejail

ARG tag=latest

OPTION overwrite=force
OPTION from=ghcr.io/daemonless/immich-ml:${tag}
appjail oci run -Pd \
  -o overwrite=force \
  -o container="args:--pull" \
  -o virtualnet=":<random> default" \
  -o nat \
  -o expose="3003:3003 proto:tcp" \
  -e MACHINE_LEARNING_HOST=0.0.0.0 \
  -e MACHINE_LEARNING_PORT=3003 \
  -e MACHINE_LEARNING_CACHE_FOLDER=/cache \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=UTC \
  -e MACHINE_LEARNING_WORKERS=1 \
  -e MACHINE_LEARNING_WORKER_TIMEOUT=300 \
  -e SKIP_CHOWN=true \
  -o fstab="/path/to/containers/immich-ml/cache /cache <pseudofs>" \
  -o fstab="/path/to/containers/immich-ml /config <pseudofs>" \
  ghcr.io/daemonless/immich-ml:latest immich-ml

Interactive Configuration

Parameters

Environment Variables

Variable Default Description
MACHINE_LEARNING_HOST 0.0.0.0 Host to bind to (0.0.0.0)
MACHINE_LEARNING_PORT 3003 Port to bind to (3003)
MACHINE_LEARNING_CACHE_FOLDER /cache Path to cache folder (/cache)
PUID 1000 User ID for the application process
PGID 1000 Group ID for the application process
TZ UTC Timezone for the container
MACHINE_LEARNING_WORKERS 1 Number of ML worker processes. Keep at 1 on weak / CPU-only hosts.
MACHINE_LEARNING_WORKER_TIMEOUT 300 Gunicorn worker timeout in seconds. Raise on slow CPUs so model loading doesn't time out and cycle the worker.
SKIP_CHOWN true Skip the one-time recursive chown of /cache and /config once ownership is recorded in /config/.chown_done (default true). Set false to force a chown on every start.

Volumes

Path Description
/cache Model cache (HuggingFace ONNX models). Use a persistent volume to avoid re-downloading models.
/config Gunicorn HOME and the .chown_done ownership marker. Must be a persistent volume (the chown-skip relies on it).

Ports

Port Protocol Description
3003 TCP ML API

This image is part of the Immich Stack.

Low-power / CPU-only hosts

On weak or CPU-only machines, model loading can be slow and the worker may time out during startup (repeated healthy/unhealthy cycles). Raise the timeout and pin the numeric libraries to a single thread to avoid thrashing:

1
2
3
4
5
6
7
8
9
environment:
  MACHINE_LEARNING_WORKERS: "1"
  MACHINE_LEARNING_WORKER_TIMEOUT: "300"
  MACHINE_LEARNING_MODEL_INTER_OP_THREADS: "1"
  MACHINE_LEARNING_MODEL_INTRA_OP_THREADS: "1"
  MACHINE_LEARNING_REQUEST_THREADS: "1"
  OMP_NUM_THREADS: "1"
  OPENBLAS_NUM_THREADS: "1"
  MKL_NUM_THREADS: "1"

Persistent volumes

Mount both /config and /cache as persistent volumes. The one-time recursive chown is skipped on later starts via a /config/.chown_done marker — without a persistent /config, the marker is lost and the chown re-runs every start, so SKIP_CHOWN=true only takes effect once /config persists the marker.

Implementation Details

  • Architectures: amd64
  • User: bsd (UID/GID set via PUID/PGID). Defaults to 1000:1000.
  • Base: Built on ghcr.io/daemonless/base (FreeBSD 15.1).

Need help? Join our Discord community.