Immich: Machine Learning, GPU Acceleration, and Storage Management (Part 2)
Complete guide to optimizing Immich. Configure hardware GPU acceleration for facial recognition, manage storage, and mount external libraries.
Hardware GPU Acceleration Configuration
Hardware acceleration significantly accelerates machine learning tasks (object detection, facial recognition, CLIP search) and transcoding.
NVIDIA GPU Passthrough (CUDA)
To leverage NVIDIA GPUs for the immich-machine-learning and immich-server containers, the host must have the NVIDIA driver and nvidia-container-toolkit installed.
Ensure the Docker daemon is configured to use the NVIDIA runtime by editing /etc/docker/daemon.json:
{
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
In your docker-compose.yml, pass the GPU through to the immich-machine-learning service:
version: '3.8'
services:
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:release-cuda
volumes:
- model-cache:/cache
environment:
- IMMICH_MEDIA_LOCATION=/usr/src/app/upload
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
restart: always
volumes:
model-cache:
For hardware-accelerated video transcoding, configure the immich-server container under the environment and deploy blocks:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:release
# ... other settings ...
environment:
- IMMICH_MEDIA_LOCATION=/usr/src/app/upload
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
Intel GPU Passthrough (QuickSync/VAAPI)
Intel GPUs use VAAPI (Video Acceleration API) and QuickSync for transcoding, and OpenVINO for machine learning inference.
To expose the Intel GPU, map the direct rendering infrastructure devices (/dev/dri) from the host into the containers.
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:release
devices:
- /dev/dri:/dev/dri
# ... other settings ...
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:release
devices:
- /dev/dri:/dev/dri
# Optional environment variables to force OpenVINO device selection
environment:
- IMMICH_MACHINE_LEARNING_DEVICE=openvino
- OPENVINO_DEVICE=GPU
Verify device permissions on the host. The container user needs read/write access to /dev/dri/renderD128. Run ls -l /dev/dri on your host to check the group ID (often render or video), and ensure your Docker container runs with the correct group membership:
group_add:
- "105" # Match host's 'render' or 'video' group GID
Machine Learning Container Tuning
The immich-machine-learning container handles computationally heavy tasks like facial detection (InsightFace) and semantic search (CLIP). Tuning this service prevents CPU/GPU bottlenecks.
Device Selection & Acceleration Backend
Configure the inference engine via the environment variables inside immich-machine-learning:
IMMICH_MACHINE_LEARNING_DEVICE: Controls the execution device. Options arecpu,cuda, oropenvino.MACHINE_LEARNING_GPU_ACCELERATION: Set totrueto enable GPU acceleration for models.
environment:
- IMMICH_MACHINE_LEARNING_DEVICE=cuda # or openvino / cpu
- MACHINE_LEARNING_GPU_ACCELERATION=true
Model Cache Persistent Storage
Avoid downloading the ML models every time the container restarts by mounting a dedicated cache volume. The default cache directory is /cache.
volumes:
- model-cache:/cache
CPU-Only Tuning (Thread/Concurrency Optimization)
If running without a dedicated GPU, limit thread utilization to prevent the container from starving the host OS or immich-server.
Set thread counts explicitly using PyTorch and ONNX Runtime environment variables:
environment:
- OMP_NUM_THREADS=4
- MKL_NUM_THREADS=4
- OPENBLAS_NUM_THREADS=4
- VECLIB_MAXIMUM_THREADS=4
- NUMEXPR_NUM_THREADS=4
- ONNXRUNTIME_CPU_THREAD_LIMIT=4
Align these limits with the physical cores available on your system, leaving headroom for PostgreSQL and Node.js server operations.
PostgreSQL & Pgvector Tuning
Immich stores high-dimensional image embeddings generated by CLIP in a PostgreSQL database using the pgvector extension. Large library sizes require optimizing memory configurations and indexing strategies.
Core Database Memory Configuration
Modify your PostgreSQL configuration (postgresql.conf or using Docker command-line overrides) to optimize for the vector search workload:
# Memory Configuration for a 16GB RAM System
shared_buffers = 4GB # 25% of total system memory
work_mem = 64MB # Memory per-operation for sorting and hashing
maintenance_work_mem = 2GB # High allocation to speed up HNSW index creation
effective_cache_size = 12GB # Estimate of total memory available for caching
For docker-compose setups, pass configuration flags directly via the command block:
database:
container_name: immich_postgres
image: tensorchord/pgvecto-rs:pg16-v0.2.0
environment:
- POSTGRES_PASSWORD=X7z9UsI4nuar0YwnucxpUG77
- POSTGRES_USER=postgres
- POSTGRES_DB=immich
volumes:
- pgdata:/var/lib/postgresql/data
command: >
postgres
-c shared_buffers=4GB
-c work_mem=64MB
-c maintenance_work_mem=2GB
-c effective_cache_size=12GB
restart: always
Vector Index Optimizations
Immich utilizes Hierarchical Navigable Small World (HNSW) indexes for efficient approximate nearest neighbor (ANN) vector search.
During initial bulk importing, index creation can consume substantial CPU and RAM. Adjust maintenance parameters to prevent out-of-memory (OOM) crashes:
- Index Build Tuning: Increase
maintenance_work_memto prevent swapping to disk during indexing. - pgvector HNSW Parameters: Ensure database tables do not timeout during query operations by adjusting the index build options.
You can verify the current indexes by logging into the PostgreSQL container:
docker exec -it immich_postgres psql -U postgres -d immich
Check existing vector indexes:
SELECT relname, indexrelname, amname FROM pg_stat_all_indexes WHERE schemaname = 'public';
Mounting External Storage Safely
By default, Immich manages all uploads in its internal upload directory. To index pre-existing photo libraries without moving or copying files, configure external libraries.
Host Path Bind Mounts
Mount the external directories into the immich-server and immich-machine-learning containers as read-only. This protects your primary archives from accidental deletions or modifications by Immich.
services:
immich-server:
# ...
volumes:
- immich-data:/usr/src/app/upload
- /mnt/nas/photos/archive:/usr/src/app/external/archive:ro
immich-machine-learning:
# ...
volumes:
- model-cache:/cache
- /mnt/nas/photos/archive:/usr/src/app/external/archive:ro
[!IMPORTANT] The paths mounted under/usr/src/app/external/must match exactly between theimmich-serverandimmich-machine-learningcontainers. Discrepancies will cause machine learning jobs to fail because the path references saved in the database won't resolve correctly inside the ML container.
User and Group Permission Alignment
Ensure the user inside the container has read access to the mounted host directories. Immich containers typically run as user node (UID 1000) or root, but can be forced to run as specific system users.
Check the ownership of the files on the host:
ls -ld /mnt/nas/photos/archive
If the host folder is owned by UID 1024 and GID 100, specify the environment variable in your .env and map it in the compose file if your container image supports user mapping, or adjust host permissions to grant read/execute permissions:
# Allow read-only access for others on the host directory
chmod -R o+rX /mnt/nas/photos/archive
Adding the Library in the Immich UI
Once the paths are mounted: 1. Navigate to Administration -> External Libraries in the Immich Web UI. 2. Click Create Library. 3. Under Import Paths, add the path mapped inside the container (e.g., /usr/src/app/external/archive). 4. Run the Scan Library job to index the assets safely.