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. Immich https://immich.app 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 /axonasif/immich-nix/blob/main/UPGRADING.md 59-coreml-on-apple-silicon--model-specific-routing for the implementation rationale and measurements. - Nix https://nixos.org/download/ 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 https://nixos.org/download/ 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 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 or HDD | SSD | | IMMICH DB VECTOR EXTENSION | Force pgvector or vectorchord ; 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 loading 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 loader-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 /axonasif/immich-nix/blob/main/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 /axonasif/immich-nix/blob/main/UPGRADING.md 4-verification-checklist remains the release acceptance procedure. Read UPGRADING.md /axonasif/immich-nix/blob/main/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 https://docs.immich.app remain authoritative. This project is licensed under the GNU Affero General Public License v3.0 only /axonasif/immich-nix/blob/main/LICENSE AGPL-3.0-only . Immich, base-images, and other third-party components retain their respective copyrights and licenses.