cd /news/artificial-intelligence/nix-flake-for-running-immich-nativel… · home topics artificial-intelligence article
[ARTICLE · art-123046] src=github.com ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Nix flake for running Immich natively on macOS with GPU accel and Linux

A new Nix flake project, immich-nix by axonasif, enables running the Immich photo-management application natively on Apple Silicon macOS and aarch64/x86_64 Linux without Docker, using Nix to supply the build toolchain, PostgreSQL, and Valkey. On an M1 Pro, GPU-accelerated machine learning via CoreML achieved 32–37 images per second for smart-search indexing with the ViT-SO400M-16-SigLIP2-384__webli model, compared with 3–10 images per second on CPU, and ~120 images per second with the smaller ViT-B-16-SigLIP2__webli model. The project is an independent deployment method, not an official Immich distribution, and upstream recommends Docker Compose for production.

read9 min views1 publishedSep 8, 2026
Nix flake for running Immich natively on macOS with GPU accel and Linux
Image: Michielbdejong (auto-discovered)

Immich built and run natively with Nix, without Docker. Apple Silicon macOS and aarch64/x86_64 Linux are supported. GPU-accelerated machine learning is available on Apple Silicon through CoreML.

This project provides a low-complexity, single-host deployment designed for macOS and Linux. Nix supplies the build toolchain, native libraries, PostgreSQL, and Valkey, while Immich is built from its pinned upstream source with its own pnpm and uv workflows. Application data, runtime state, and build outputs remain inside the repository by default.

This is an independent deployment method, not an official Immich distribution. Upstream recommends Docker Compose for production installations.

Packaging Immich as a conventional Nix derivation would require maintaining pnpmDeps hashes and a separate Python package set. It also encounters two Darwin-specific limitations: nixpkgs marks extism-js-core as broken on Darwin, and its ONNX Runtime build does not include the CoreML execution provider. Building with upstream's package managers avoids both constraints, at the cost of network-dependent, non-hermetic builds.

On Apple Silicon, the local machine-learning patch selects a working execution route for each model family. In testing on an M1 Pro, smart-search indexing reached 32–37 images per second with CoreML with the immich-app/ViT-SO400M-16-SigLIP2-384__webli model, compared with 3-10 images per second on CPU. With the smaller ViT-B-16-SigLIP2__webli model, you can get ~120 images per second on M1 Pro. The patch also avoids an ONNX Runtime issue that can expand the SO400M text model into a 6.5 GB CoreML program. See UPGRADING.md for the implementation rationale and measurements.

  • Nix with flakes enabled
  • Apple Silicon macOS, or aarch64/x86_64 Linux

macOS does not require Homebrew or Xcode. System installations of Node.js and Python are not required on either platform. Your system is not polluted.

For macOS, use the official multi-user installer:

curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install | sh

Linux installation #

For Linux systems using systemd with SELinux disabled, use the recommended multi-user installation:

curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install | sh -s -- --daemon

After installation, start a new shell and enable the Nix command interface and flakes with the following commands:

mkdir -p ~/.config/nix
echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf

See the official Nix download and installation instructions for other configurations, single-user installation, and troubleshooting.

The repository contains pinned Immich and base-images submodules and must be cloned recursively:

git clone --depth 1 --recurse-submodules --shallow-submodules https://github.com/axonasif/immich-nix.git
cd immich-nix

Build the complete stack once:

nix develop --command scripts/build.sh

Then start Immich:

nix develop --command scripts/immich.sh start

The web application is then available at http://0.0.0.0:2283. The initial build downloads the nixpkgs closure and application dependencies, then compiles sharp against the Nix-provided libvips. Subsequent builds reuse downloaded dependencies and are substantially faster.

By default, the assembled application is stored in .local/immich-app, while PostgreSQL, Valkey, logs, cached models, and media are stored in .local/immich-run. No files are installed system-wide. Consequently, removing the checkout also removes all data stored in these default locations.

Run nix develop to enter the immich env shell first to use the commands below easily.

scripts/immich.sh status
scripts/immich.sh logs
scripts/immich.sh stop
scripts/immich.sh restart

The upstream CLI and administration tool are included in the build:

export PATH="$PWD/.local/immich-app/bin:$PATH"
immich --help
immich-admin --help

The default paths isolate a fresh checkout from any existing Immich installation. To use an existing PostgreSQL cluster or media library, define the relevant paths before starting the stack:

export IMMICH_PGDATA=/path/to/postgres
export IMMICH_MEDIA_DIR=/path/to/media

Warning

Immich runs irreversible schema migrations on first start. Create a database backup before using an existing cluster. The cluster's PostgreSQL major version must match nix/shell.nix, which currently provides PostgreSQL 17.

The runner supports the following configuration variables:

Variable Purpose Default
IMMICH_PREFIX Assembled application path .local/immich-app
IMMICH_STATE_DIR Runtime state root .local/immich-run
IMMICH_PGDATA PostgreSQL data directory $IMMICH_STATE_DIR/postgres
IMMICH_PGSOCKET_DIR PostgreSQL Unix-socket directory $TMPDIR/immich-nix-pgsocket
IMMICH_MEDIA_DIR Immich media directory $IMMICH_STATE_DIR/media
IMMICH_CACHE_DIR Machine-learning model cache $IMMICH_MEDIA_DIR/cache
IMMICH_HTTP_HOST ,IMMICH_HTTP_PORT Server bind address and port 0.0.0.0 ,2283
IMMICH_ML_HOST ,IMMICH_ML_PORT Machine-learning bind address and port 127.0.0.1 ,3003
IMMICH_PG_PORT PostgreSQL port 5433
IMMICH_REDIS_HOST ,IMMICH_REDIS_PORT Valkey bind address and port 127.0.0.1 ,6380
IMMICH_DB_STORAGE_TYPE PostgreSQL tuning profile ( SSD orHDD ) SSD
IMMICH_DB_VECTOR_EXTENSION Force pgvector orvectorchord ; unset allows Immich to auto-select VectorChord unset
IMMICH_ML_WORKERS Machine-learning worker count 1
IMMICH_ML_WORKER_TIMEOUT Gunicorn timeout when the CoreML execution path is disabled 300 seconds
MACHINE_LEARNING_DISABLE_COREML Set to 1 to disable CoreML and run machine learning on CPU unset

The current revision targets Immich v3.1.0 and was last tested against that release on macOS on 2026-09-03 and Linux on 2026-09-04. The status terms distinguish components built directly from upstream (“Aligned”), native or platform-specific implementations intended to preserve the same feature behavior (“Adapted”), and incomplete operational parity (“Partial”). This is a compatibility map, not a claim that the project reproduces every Docker-specific behavior or an exhaustive test matrix.

Area Status Scope and differences
Server, API, and background workers Aligned Built from the pinned Immich source and run through the upstream node dist/main entry point.
Web application Aligned Built from the pinned Immich source and served by the Immich server.
Machine learning Adapted Uses upstream Python dependencies and CPU wheels. On Apple Silicon, a local patch routes smart search, face recognition, and OCR through model-specific CoreML representations; the SO400M text encoder remains on CPU. CoreML can be disabled.
Core WASM plugin Aligned Built from upstream source with the extism-js release and checksum pinned by Immich. Plugin must be checked after upgrades because failure is otherwise non-fatal.
Immich CLI and immich-admin Aligned Built from the pinned upstream source and installed with local wrappers.
Image and video processing Adapted Uses the upstream libvips build choices and -priority patch, plus Jellyfin FFmpeg and the required native codecs from Nix. Some library patch versions may be newer than the upstream image.
Reverse geocoding Aligned Uses the geodata payload extracted from the exact production base image pinned by the Immich release.
PostgreSQL and vector search Adapted Runs PostgreSQL 17 with pgvector and VectorChord. Upstream database settings are translated where applicable; the macOS effective_io_concurrency exception is retained.
Existing pgvector databases Supported Immich can retain pgvector or migrate it to VectorChord. Set IMMICH_DB_VECTOR_EXTENSION=pgvector to postpone migration.
Legacy pgvecto.rs ( vectors ) databases Migration required pgvecto.rs is not packaged. Such databases must follow Immich's standalone PostgreSQL migration procedure before use.
Valkey Adapted Uses the Nix-provided Valkey package with Immich's existing Redis environment contract.
Scheduled database backups Adapted Immich's Debian-specific PostgreSQL binary path is patched to use the matching Nix-provided tools on PATH .
Process lifecycle and health monitoring Partial The runner provides start, stop, restart, status, startup readiness checks, and logs. Docker restart policies and periodic container health checks are not reproduced.

Platform support:

Platform Status Notes
Apple Silicon macOS ( aarch64-darwin ) Supported Includes CoreML acceleration.
Intel macOS ( x86_64-darwin ) Not currently supported No matching extism-js release artifact is pinned. Nixpkgs is also dropping Intel Mac support.
Linux ( aarch64-linux ,x86_64-linux ) Supported The flake and upstream-pinned extism-js artifacts cover both architectures; machine learning uses ONNX Runtime CPU.

The detailed alignment procedure, known divergences, and verification checklist are maintained in UPGRADING.md. Compatibility should be re-established whenever immich-version, flake.lock, or native library pins change.

Path Purpose
LICENSE GNU Affero General Public License v3.0
UPGRADING.md Version-alignment process, failure modes, and verification checklist
immich-version Authoritative Immich release tag
flake.nix ,flake.lock Pinned nixpkgs input and development-shell outputs
nix/shell.nix Toolchain, services, and native libraries
nix/extism-js.nix Upstream extism-js release artifact used to build the WASM plugin
nix/geodata.nix Fixed-output reverse-geocoding data from the upstream image
nix/patches/ libvips patch vendored from upstream base-images
scripts/build.sh Source build and runtime-tree assembly
scripts/immich.sh Native service runner
scripts/test.sh Disposable native integration test runner
scripts/patch-postgres-bin-path.py PostgreSQL backup-command path adaptation
scripts/patch-coreml.py Apple Silicon CoreML routing and CPU fallback
scripts/show-upstream-pins.sh Comparison of an Immich release with repository pins
tests/native-smoke.py Public API and deployed CLI media-lifecycle checks
tests/ml-smoke.py Real CLIP, face-recognition, and OCR inference checks
upstream/immich Pinned Immich source submodule used for the build
upstream/base-images Pinned upstream native-library reference submodule
.local/immich-app Generated application tree (ignored by Git)
.local/immich-run Generated runtime state (ignored by Git)

Run the native integration suite against a fresh disposable database and media store:

nix develop --command scripts/test.sh quick

This checks the assembled build, starts the complete native stack on isolated ports, uploads generated photo and video fixtures through the deployed CLI, waits for metadata extraction, thumbnail generation, and video transcoding, verifies persistence across a complete restart, deletes the assets, and checks clean shutdown. It also verifies PostgreSQL checksums, VectorChord indexes, Valkey, the web application, the core plugin, and repository-local state.

The full mode additionally configures and exercises ViT-SO400M-16-SigLIP2-384__webli smart search, buffalo_l face recognition, and PP-OCRv5_server OCR through Immich, then calls each model family directly:

nix develop --command scripts/test.sh full

Model downloads are cached under .local/immich-test/model-cache; all other test state is recreated on every run. The integration suite covers this project's native adaptation boundary. The broader manual upgrade checklist in UPGRADING.md remains the release acceptance procedure.

Read UPGRADING.md before changing the version. An upgrade can change the Node.js, pnpm, Python, extism-js, libvips, media-library, database, and service-runtime contracts in addition to the Immich source tag.

Begin by comparing the target release with the repository's pins:

nix develop --command scripts/show-upstream-pins.sh v3.2.0

After updating nix/ and immich-version, rebuild and complete the verification checklist in UPGRADING.md against both a fresh database and a disposable copy of the previous version's database. scripts/build.sh checks out the selected tag in upstream/immich; the resulting submodule pointer must be recorded as part of a version update.

Maintenance findings in UPGRADING.md are version-specific. The source tree, base-images revision, release notes, and official Immich documentation remain authoritative.

This project is licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only). Immich, base-images, and other third-party components retain their respective copyrights and licenses.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @immich 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/nix-flake-for-runnin…] indexed:0 read:9min 2026-09-08 ·