{ lib, stdenvNoCC, buildNpmPackage, fetchFromGitHub, python3, nodejs, nodePackages, runCommand, nixosTests, callPackage, # build-time deps glib, pkg-config, makeWrapper, curl, cacert, unzip, # runtime deps ffmpeg-headless, imagemagick, libraw, libheif, vips, perl, }: let buildNpmPackage' = buildNpmPackage.override { inherit nodejs; }; sources = lib.importJSON ./sources.json; inherit (sources) version; buildLock = { sources = builtins.map (p: { name = p.pname; inherit (p) version; inherit (p.src) rev; }) [ imagemagick libheif libraw ]; packages = [ ]; }; # The geodata website is not versioned, so we use the internet archive geodata = runCommand "immich-geodata" { outputHash = "sha256-imqSfzXaEMNo9T9tZr80sr/89n19kiFc8qwidFzRUaY="; outputHashMode = "recursive"; nativeBuildInputs = [ cacert curl unzip ]; meta.license = lib.licenses.cc-by-40; } '' mkdir $out url="https://web.archive.org/web/20240724153050/http://download.geonames.org/export/dump" curl -Lo ./cities500.zip "$url/cities500.zip" curl -Lo $out/admin1CodesASCII.txt "$url/admin1CodesASCII.txt" curl -Lo $out/admin2Codes.txt "$url/admin2Codes.txt" curl -Lo $out/ne_10m_admin_0_countries.geojson \ https://raw.githubusercontent.com/nvkelso/natural-earth-vector/ca96624a56bd078437bca8184e78163e5039ad19/geojson/ne_10m_admin_0_countries.geojson unzip ./cities500.zip -d $out/ echo "2024-07-24T15:30:50Z" > $out/geodata-date.txt ''; src = fetchFromGitHub { owner = "immich-app"; repo = "immich"; rev = "v${version}"; inherit (sources) hash; }; openapi = buildNpmPackage' { pname = "immich-openapi-sdk"; inherit version; src = "${src}/open-api/typescript-sdk"; inherit (sources.components."open-api/typescript-sdk") npmDepsHash; installPhase = '' runHook preInstall npm config delete cache npm prune --omit=dev --omit=optional mkdir -p $out mv package.json package-lock.json node_modules build $out/ runHook postInstall ''; }; web = buildNpmPackage' { pname = "immich-web"; inherit version; src = "${src}/web"; inherit (sources.components.web) npmDepsHash; preBuild = '' rm node_modules/@immich/sdk ln -s ${openapi} node_modules/@immich/sdk # Rollup does not find the dependency otherwise ln -s node_modules/@immich/sdk/node_modules/@oazapfts node_modules/ ''; installPhase = '' runHook preInstall cp -r build $out runHook postInstall ''; }; node-addon-api = stdenvNoCC.mkDerivation rec { pname = "node-addon-api"; version = "8.0.0"; src = fetchFromGitHub { owner = "nodejs"; repo = "node-addon-api"; rev = "v${version}"; hash = "sha256-k3v8lK7uaEJvcaj1sucTjFZ6+i5A6w/0Uj9rYlPhjCE="; }; installPhase = '' mkdir $out cp -r *.c *.h *.gyp *.gypi index.js package-support.json package.json tools $out/ ''; }; vips' = vips.overrideAttrs (prev: { mesonFlags = prev.mesonFlags ++ [ "-Dtiff=disabled" ]; }); in buildNpmPackage' { pname = "immich"; inherit version; src = "${src}/server"; inherit (sources.components.server) npmDepsHash; nativeBuildInputs = [ pkg-config python3 makeWrapper glib.dev nodePackages.node-gyp ]; buildInputs = [ ffmpeg-headless imagemagick libraw libheif vips' # Required for sharp ]; # Required because vips tries to write to the cache dir makeCacheWritable = true; preBuild = '' cd node_modules/sharp mkdir node_modules ln -s ${node-addon-api} node_modules/node-addon-api ${lib.getExe nodejs} install/check rm -r node_modules cd ../.. rm -r node_modules/@img/sharp* ''; installPhase = '' runHook preInstall npm config delete cache npm prune --omit=dev mkdir -p $out/build mv package.json package-lock.json node_modules dist resources $out/ ln -s ${web} $out/build/www ln -s ${geodata} $out/build/geodata echo '${builtins.toJSON buildLock}' > $out/build/build-lock.json makeWrapper ${lib.getExe nodejs} $out/bin/admin-cli --add-flags $out/dist/main --add-flags cli makeWrapper ${lib.getExe nodejs} $out/bin/server --add-flags $out/dist/main --chdir $out \ --set IMMICH_BUILD_DATA $out/build --set NODE_ENV production \ --suffix PATH : "${ lib.makeBinPath [ perl ffmpeg-headless ] }" runHook postInstall ''; passthru = { tests = { inherit (nixosTests) immich; }; cli = callPackage ./cli.nix { buildNpmPackage = buildNpmPackage'; inherit src; }; machine-learning = callPackage ./machine-learning.nix { inherit src; }; inherit web geodata; updateScript = ./update.sh; }; meta = { description = "Self-hosted photo and video backup solution"; homepage = "https://immich.app/"; license = lib.licenses.agpl3Only; maintainers = with lib.maintainers; [ jvanbruegge ]; platforms = lib.platforms.linux; mainProgram = "server"; }; }