{"slug": "nix-flake-for-running-immich-natively-on-macos-with-gpu-accel-and-linux", "title": "Nix flake for running Immich natively on macOS with GPU accel and Linux", "summary": "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.", "body_md": "[Immich](https://immich.app) built and run natively with Nix, without Docker.\nApple Silicon macOS and aarch64/x86_64 Linux are supported. GPU-accelerated\nmachine learning is available on Apple Silicon through CoreML.\n\nThis project provides a low-complexity, single-host deployment designed for\nmacOS and Linux. Nix supplies the build toolchain, native libraries, PostgreSQL,\nand Valkey, while Immich is built from its pinned upstream source with its own\n`pnpm` and `uv` workflows. Application data, runtime state, and build outputs\nremain inside the repository by default.\n\nThis is an independent deployment method, not an official Immich distribution. Upstream recommends Docker Compose for production installations.\n\nPackaging Immich as a conventional Nix derivation would require maintaining\n`pnpmDeps` hashes and a separate Python package set. It also encounters two\nDarwin-specific limitations: nixpkgs marks `extism-js-core` as broken on\nDarwin, and its ONNX Runtime build does not include the CoreML execution\nprovider. Building with upstream's package managers avoids both constraints,\nat the cost of network-dependent, non-hermetic builds.\n\nOn Apple Silicon, the local machine-learning patch selects a working execution\nroute for each model family. In testing on an M1 Pro, smart-search indexing\nreached 32–37 images per second with CoreML with the `immich-app/ViT-SO400M-16-SigLIP2-384__webli` model, compared with 3-10 images per\nsecond 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\nSO400M text model into a 6.5 GB CoreML program. See\n[UPGRADING.md](/axonasif/immich-nix/blob/main/UPGRADING.md#59-coreml-on-apple-silicon--model-specific-routing)\nfor the implementation rationale and measurements.\n\n- [Nix](https://nixos.org/download/) with flakes enabled\n- Apple Silicon macOS, or aarch64/x86_64 Linux\n\nmacOS does not require Homebrew or Xcode. System installations of Node.js and Python are not required on either platform. Your system is not polluted.\n\nFor macOS, use the official multi-user installer:\n\n```\ncurl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install | sh\n```\n\n## Linux installation\n\nFor Linux systems using systemd with SELinux disabled, use the recommended multi-user installation:\n\n```\ncurl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install | sh -s -- --daemon\n```\n\nAfter installation, start a new shell and enable the Nix command interface and flakes with the following commands:\n\n```\nmkdir -p ~/.config/nix\necho 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf\n```\n\nSee the official [Nix download and installation\ninstructions](https://nixos.org/download/) for other configurations,\nsingle-user installation, and troubleshooting.\n\nThe repository contains pinned Immich and base-images submodules and must be cloned recursively:\n\n```\ngit clone --depth 1 --recurse-submodules --shallow-submodules https://github.com/axonasif/immich-nix.git\ncd immich-nix\n```\n\nBuild the complete stack once:\n\n```\nnix develop --command scripts/build.sh\n```\n\nThen start Immich:\n\n```\nnix develop --command scripts/immich.sh start\n```\n\nThe web application is then available at [http://0.0.0.0:2283](http://0.0.0.0:2283). The initial\nbuild downloads the nixpkgs closure and application dependencies, then compiles\n`sharp` against the Nix-provided libvips. Subsequent builds reuse downloaded\ndependencies and are substantially faster.\n\nBy default, the assembled application is stored in `.local/immich-app`, while\nPostgreSQL, Valkey, logs, cached models, and media are stored in\n`.local/immich-run`. No files are installed system-wide. Consequently, removing\nthe checkout also removes all data stored in these default locations.\n\nRun `nix develop` to enter the immich env shell first to use the commands below easily.\n\n```\nscripts/immich.sh status\nscripts/immich.sh logs\nscripts/immich.sh stop\nscripts/immich.sh restart\n```\n\nThe upstream CLI and administration tool are included in the build:\n\n```\nexport PATH=\"$PWD/.local/immich-app/bin:$PATH\"\nimmich --help\nimmich-admin --help\n```\n\nThe 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:\n\n```\nexport IMMICH_PGDATA=/path/to/postgres\nexport IMMICH_MEDIA_DIR=/path/to/media\n```\n\nWarning\n\nImmich runs irreversible schema migrations on first start. Create a database\nbackup before using an existing cluster. The cluster's PostgreSQL major\nversion must match `nix/shell.nix`, which currently provides PostgreSQL 17.\n\nThe runner supports the following configuration variables:\n\n| Variable | Purpose | Default | \n|---|---|---|\n| `IMMICH_PREFIX` | Assembled application path | `.local/immich-app` | \n| `IMMICH_STATE_DIR` | Runtime state root | `.local/immich-run` | \n| `IMMICH_PGDATA` | PostgreSQL data directory | `$IMMICH_STATE_DIR/postgres` | \n| `IMMICH_PGSOCKET_DIR` | PostgreSQL Unix-socket directory | `$TMPDIR/immich-nix-pgsocket` | \n| `IMMICH_MEDIA_DIR` | Immich media directory | `$IMMICH_STATE_DIR/media` | \n| `IMMICH_CACHE_DIR` | Machine-learning model cache | `$IMMICH_MEDIA_DIR/cache` | \n| `IMMICH_HTTP_HOST` ,`IMMICH_HTTP_PORT` | Server bind address and port | `0.0.0.0` ,`2283` | \n| `IMMICH_ML_HOST` ,`IMMICH_ML_PORT` | Machine-learning bind address and port | `127.0.0.1` ,`3003` | \n| `IMMICH_PG_PORT` | PostgreSQL port | `5433` | \n| `IMMICH_REDIS_HOST` ,`IMMICH_REDIS_PORT` | Valkey bind address and port | `127.0.0.1` ,`6380` | \n| `IMMICH_DB_STORAGE_TYPE` | PostgreSQL tuning profile ( `SSD` or`HDD` ) | `SSD` | \n| `IMMICH_DB_VECTOR_EXTENSION` | Force `pgvector` or`vectorchord` ; unset allows Immich to auto-select VectorChord | unset | \n| `IMMICH_ML_WORKERS` | Machine-learning worker count | `1` | \n| `IMMICH_ML_WORKER_TIMEOUT` | Gunicorn timeout when the CoreML execution path is disabled | `300` seconds | \n| `MACHINE_LEARNING_DISABLE_COREML` | Set to `1` to disable CoreML and run machine learning on CPU | unset | \n\nThe current revision targets **Immich v3.1.0** and was last tested against that\nrelease on macOS on **2026-09-03** and Linux on **2026-09-04**. The status\nterms distinguish components built directly from upstream (“Aligned”), native\nor platform-specific implementations intended to preserve the same feature\nbehavior (“Adapted”), and incomplete operational parity (“Partial”). This is a\ncompatibility map, not a claim that the project reproduces every Docker-specific\nbehavior or an exhaustive test matrix.\n\n| Area | Status | Scope and differences | \n|---|---|---|\n| Server, API, and background workers | Aligned | Built from the pinned Immich source and run through the upstream `node dist/main` entry point. | \n| Web application | Aligned | Built from the pinned Immich source and served by the Immich server. | \n| 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. | \n| Core WASM plugin | Aligned | Built from upstream source with the `extism-js` release and checksum pinned by Immich. Plugin loading must be checked after upgrades because failure is otherwise non-fatal. | \n| Immich CLI and `immich-admin` | Aligned | Built from the pinned upstream source and installed with local wrappers. | \n| Image and video processing | Adapted | Uses the upstream libvips build choices and loader-priority patch, plus Jellyfin FFmpeg and the required native codecs from Nix. Some library patch versions may be newer than the upstream image. | \n| Reverse geocoding | Aligned | Uses the geodata payload extracted from the exact production base image pinned by the Immich release. | \n| 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. | \n| Existing pgvector databases | Supported | Immich can retain pgvector or migrate it to VectorChord. Set `IMMICH_DB_VECTOR_EXTENSION=pgvector` to postpone migration. | \n| Legacy pgvecto.rs ( `vectors` ) databases | Migration required | pgvecto.rs is not packaged. Such databases must follow Immich's standalone PostgreSQL migration procedure before use. | \n| Valkey | Adapted | Uses the Nix-provided Valkey package with Immich's existing Redis environment contract. | \n| Scheduled database backups | Adapted | Immich's Debian-specific PostgreSQL binary path is patched to use the matching Nix-provided tools on `PATH` . | \n| 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. | \n\nPlatform support:\n\n| Platform | Status | Notes | \n|---|---|---|\n| Apple Silicon macOS ( `aarch64-darwin` ) | Supported | Includes CoreML acceleration. | \n| Intel macOS ( `x86_64-darwin` ) | Not currently supported | No matching `extism-js` release artifact is pinned. Nixpkgs is also dropping Intel Mac support. | \n| Linux ( `aarch64-linux` ,`x86_64-linux` ) | Supported | The flake and upstream-pinned `extism-js` artifacts cover both architectures; machine learning uses ONNX Runtime CPU. | \n\nThe detailed alignment procedure, known divergences, and verification checklist\nare maintained in [UPGRADING.md](/axonasif/immich-nix/blob/main/UPGRADING.md). Compatibility should be\nre-established whenever `immich-version`, `flake.lock`, or native library pins\nchange.\n\n| Path | Purpose | \n|---|---|\n| `LICENSE` | GNU Affero General Public License v3.0 | \n| `UPGRADING.md` | Version-alignment process, failure modes, and verification checklist | \n| `immich-version` | Authoritative Immich release tag | \n| `flake.nix` ,`flake.lock` | Pinned nixpkgs input and development-shell outputs | \n| `nix/shell.nix` | Toolchain, services, and native libraries | \n| `nix/extism-js.nix` | Upstream `extism-js` release artifact used to build the WASM plugin | \n| `nix/geodata.nix` | Fixed-output reverse-geocoding data from the upstream image | \n| `nix/patches/` | libvips patch vendored from upstream base-images | \n| `scripts/build.sh` | Source build and runtime-tree assembly | \n| `scripts/immich.sh` | Native service runner | \n| `scripts/test.sh` | Disposable native integration test runner | \n| `scripts/patch-postgres-bin-path.py` | PostgreSQL backup-command path adaptation | \n| `scripts/patch-coreml.py` | Apple Silicon CoreML routing and CPU fallback | \n| `scripts/show-upstream-pins.sh` | Comparison of an Immich release with repository pins | \n| `tests/native-smoke.py` | Public API and deployed CLI media-lifecycle checks | \n| `tests/ml-smoke.py` | Real CLIP, face-recognition, and OCR inference checks | \n| `upstream/immich` | Pinned Immich source submodule used for the build | \n| `upstream/base-images` | Pinned upstream native-library reference submodule | \n| `.local/immich-app` | Generated application tree (ignored by Git) | \n| `.local/immich-run` | Generated runtime state (ignored by Git) | \n\nRun the native integration suite against a fresh disposable database and media store:\n\n```\nnix develop --command scripts/test.sh quick\n```\n\nThis 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.\n\nThe full mode additionally configures and exercises\n`ViT-SO400M-16-SigLIP2-384__webli` smart search, `buffalo_l` face recognition,\nand `PP-OCRv5_server` OCR through Immich, then calls each model family directly:\n\n```\nnix develop --command scripts/test.sh full\n```\n\nModel downloads are cached under `.local/immich-test/model-cache`; all other\ntest state is recreated on every run. The integration suite covers this\nproject's native adaptation boundary. The broader manual upgrade checklist in\n[UPGRADING.md](/axonasif/immich-nix/blob/main/UPGRADING.md#4-verification-checklist) remains the release\nacceptance procedure.\n\nRead [UPGRADING.md](/axonasif/immich-nix/blob/main/UPGRADING.md) before changing the version. An upgrade can\nchange the Node.js, pnpm, Python, `extism-js`, libvips, media-library, database,\nand service-runtime contracts in addition to the Immich source tag.\n\nBegin by comparing the target release with the repository's pins:\n\n```\nnix develop --command scripts/show-upstream-pins.sh v3.2.0\n```\n\nAfter updating `nix/` and `immich-version`, rebuild and complete the verification\nchecklist in `UPGRADING.md` against both a fresh database and a disposable copy\nof the previous version's database. `scripts/build.sh` checks out the selected\ntag in `upstream/immich`; the resulting submodule pointer must be recorded as\npart of a version update.\n\nMaintenance findings in `UPGRADING.md` are version-specific. The source tree,\nbase-images revision, release notes, and [official Immich\ndocumentation](https://docs.immich.app) remain authoritative.\n\nThis project is licensed under the [GNU Affero General Public License v3.0\nonly](/axonasif/immich-nix/blob/main/LICENSE) (`AGPL-3.0-only`). Immich, base-images, and other third-party\ncomponents retain their respective copyrights and licenses.", "url": "https://wpnews.pro/news/nix-flake-for-running-immich-natively-on-macos-with-gpu-accel-and-linux", "canonical_source": "https://github.com/axonasif/immich-nix", "published_at": "2026-09-08 07:01:31+00:00", "updated_at": "2026-09-08 07:32:38.633625+00:00", "lang": "en", "topics": ["artificial-intelligence", "machine-learning", "developer-tools"], "entities": ["Immich", "axonasif", "Nix", "Apple Silicon", "CoreML", "ViT-SO400M-16-SigLIP2-384__webli", "ViT-B-16-SigLIP2__webli", "M1 Pro"], "alternates": {"html": "https://wpnews.pro/news/nix-flake-for-running-immich-natively-on-macos-with-gpu-accel-and-linux", "markdown": "https://wpnews.pro/news/nix-flake-for-running-immich-natively-on-macos-with-gpu-accel-and-linux.md", "text": "https://wpnews.pro/news/nix-flake-for-running-immich-natively-on-macos-with-gpu-accel-and-linux.txt", "jsonld": "https://wpnews.pro/news/nix-flake-for-running-immich-natively-on-macos-with-gpu-accel-and-linux.jsonld"}}