mirror of
https://github.com/oqyude/nixos.git
synced 2026-06-11 04:30:41 +03:00
123
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
nixpkgs.overlays = [ (import ../overlays/immich) ];
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
self: super: {
|
||||||
|
pkgs-src = {
|
||||||
|
immich = super.callPackage ./package.nix { };
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,307 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
buildNpmPackage,
|
||||||
|
fetchFromGitHub,
|
||||||
|
python3,
|
||||||
|
nodejs,
|
||||||
|
node-gyp,
|
||||||
|
runCommand,
|
||||||
|
nixosTests,
|
||||||
|
immich-machine-learning,
|
||||||
|
# build-time deps
|
||||||
|
glib,
|
||||||
|
pkg-config,
|
||||||
|
makeWrapper,
|
||||||
|
curl,
|
||||||
|
cacert,
|
||||||
|
unzip,
|
||||||
|
# runtime deps
|
||||||
|
cairo,
|
||||||
|
exiftool,
|
||||||
|
giflib,
|
||||||
|
jellyfin-ffmpeg, # Immich depends on the jellyfin customizations, see https://github.com/NixOS/nixpkgs/issues/351943
|
||||||
|
imagemagick,
|
||||||
|
libjpeg,
|
||||||
|
libpng,
|
||||||
|
libraw,
|
||||||
|
libheif,
|
||||||
|
librsvg,
|
||||||
|
pango,
|
||||||
|
perl,
|
||||||
|
pixman,
|
||||||
|
vips,
|
||||||
|
buildPackages,
|
||||||
|
sourcesJSON ? ./sources.json,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
buildNpmPackage' = buildNpmPackage.override { inherit nodejs; };
|
||||||
|
sources = lib.importJSON sourcesJSON;
|
||||||
|
inherit (sources) version;
|
||||||
|
|
||||||
|
esbuild' = buildPackages.esbuild.override {
|
||||||
|
buildGoModule =
|
||||||
|
args:
|
||||||
|
buildPackages.buildGoModule (
|
||||||
|
args
|
||||||
|
// rec {
|
||||||
|
version = "0.25.5";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "evanw";
|
||||||
|
repo = "esbuild";
|
||||||
|
tag = "v${version}";
|
||||||
|
hash = "sha256-jemGZkWmN1x2+ZzJ5cLp3MoXO0oDKjtZTmZS9Be/TDw=";
|
||||||
|
};
|
||||||
|
vendorHash = "sha256-+BfxCyg0KkDQpHt/wycy/8CTG6YBA/VJvJFhhzUnSiQ=";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 =
|
||||||
|
let
|
||||||
|
inherit (sources.components.geonames) timestamp;
|
||||||
|
date =
|
||||||
|
"${lib.substring 0 4 timestamp}-${lib.substring 4 2 timestamp}-${lib.substring 6 2 timestamp}T"
|
||||||
|
+ "${lib.substring 8 2 timestamp}:${lib.substring 10 2 timestamp}:${lib.substring 12 2 timestamp}Z";
|
||||||
|
in
|
||||||
|
runCommand "immich-geodata"
|
||||||
|
{
|
||||||
|
outputHash = sources.components.geonames.hash;
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
nativeBuildInputs = [
|
||||||
|
cacert
|
||||||
|
curl
|
||||||
|
unzip
|
||||||
|
];
|
||||||
|
|
||||||
|
meta.license = lib.licenses.cc-by-40;
|
||||||
|
}
|
||||||
|
''
|
||||||
|
mkdir $out
|
||||||
|
url="https://web.archive.org/web/${timestamp}/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://github.com/nvkelso/natural-earth-vector/raw/ca96624a56bd078437bca8184e78163e5039ad19/geojson/ne_10m_admin_0_countries.geojson
|
||||||
|
|
||||||
|
unzip ./cities500.zip -d $out/
|
||||||
|
echo "${date}" > $out/geodata-date.txt
|
||||||
|
'';
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "immich-app";
|
||||||
|
repo = "immich";
|
||||||
|
tag = "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;
|
||||||
|
sourceRoot = "${src.name}/web";
|
||||||
|
inherit (sources.components.web) npmDepsHash;
|
||||||
|
|
||||||
|
# prePatch is needed because npmConfigHook is a postPatch
|
||||||
|
prePatch = ''
|
||||||
|
# some part of the build wants to use un-prefixed binaries. let them.
|
||||||
|
mkdir -p $TMP/bin
|
||||||
|
ln -s "$(type -p ${stdenv.cc.targetPrefix}pkg-config)" $TMP/bin/pkg-config || true
|
||||||
|
ln -s "$(type -p ${stdenv.cc.targetPrefix}c++filt)" $TMP/bin/c++filt || true
|
||||||
|
ln -s "$(type -p ${stdenv.cc.targetPrefix}readelf)" $TMP/bin/readelf || true
|
||||||
|
export PATH="$TMP/bin:$PATH"
|
||||||
|
'';
|
||||||
|
|
||||||
|
preBuild = ''
|
||||||
|
rm node_modules/@immich/sdk
|
||||||
|
ln -s ${openapi} node_modules/@immich/sdk
|
||||||
|
'';
|
||||||
|
|
||||||
|
env.npm_config_build_from_source = "true";
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
# https://github.com/Automattic/node-canvas/blob/master/Readme.md#compiling
|
||||||
|
cairo
|
||||||
|
giflib
|
||||||
|
libjpeg
|
||||||
|
libpng
|
||||||
|
librsvg
|
||||||
|
pango
|
||||||
|
pixman
|
||||||
|
];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
cp -r build $out
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
vips' = vips.overrideAttrs (prev: {
|
||||||
|
mesonFlags = prev.mesonFlags ++ [ "-Dtiff=disabled" ];
|
||||||
|
});
|
||||||
|
in
|
||||||
|
buildNpmPackage' {
|
||||||
|
pname = "immich";
|
||||||
|
inherit version;
|
||||||
|
src = "${src}/server";
|
||||||
|
inherit (sources.components.server) npmDepsHash;
|
||||||
|
|
||||||
|
# prePatch is needed because npmConfigHook is a postPatch
|
||||||
|
prePatch = ''
|
||||||
|
# pg_dumpall fails without database root access
|
||||||
|
# see https://github.com/immich-app/immich/issues/13971
|
||||||
|
substituteInPlace src/services/backup.service.ts \
|
||||||
|
--replace-fail '`/usr/lib/postgresql/''${databaseMajorVersion}/bin/pg_dumpall`' '`pg_dump`'
|
||||||
|
|
||||||
|
# some part of the build wants to use un-prefixed binaries. let them.
|
||||||
|
mkdir -p $TMP/bin
|
||||||
|
ln -s "$(type -p ${stdenv.cc.targetPrefix}pkg-config)" $TMP/bin/pkg-config || true
|
||||||
|
ln -s "$(type -p ${stdenv.cc.targetPrefix}c++filt)" $TMP/bin/c++filt || true
|
||||||
|
ln -s "$(type -p ${stdenv.cc.targetPrefix}readelf)" $TMP/bin/readelf || true
|
||||||
|
export PATH="$TMP/bin:$PATH"
|
||||||
|
'';
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkg-config
|
||||||
|
python3
|
||||||
|
makeWrapper
|
||||||
|
glib
|
||||||
|
node-gyp # for building node_modules/sharp from source
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
jellyfin-ffmpeg
|
||||||
|
imagemagick
|
||||||
|
libraw
|
||||||
|
libheif
|
||||||
|
# https://github.com/Automattic/node-canvas/blob/master/Readme.md#compiling
|
||||||
|
cairo
|
||||||
|
giflib
|
||||||
|
libjpeg
|
||||||
|
libpng
|
||||||
|
librsvg
|
||||||
|
pango
|
||||||
|
pixman
|
||||||
|
# Required for sharp
|
||||||
|
vips'
|
||||||
|
];
|
||||||
|
|
||||||
|
# Required because vips tries to write to the cache dir
|
||||||
|
makeCacheWritable = true;
|
||||||
|
|
||||||
|
env.SHARP_FORCE_GLOBAL_LIBVIPS = 1;
|
||||||
|
env.ESBUILD_BINARY_PATH = lib.getExe esbuild';
|
||||||
|
|
||||||
|
preBuild = ''
|
||||||
|
# If exiftool-vendored.pl isn't found, exiftool is searched for on the PATH
|
||||||
|
rm -r node_modules/exiftool-vendored.*
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
npm config delete cache
|
||||||
|
npm prune --omit=dev
|
||||||
|
|
||||||
|
# remove build artifacts that bloat the closure
|
||||||
|
rm -r node_modules/**/{*.target.mk,binding.Makefile,config.gypi,Makefile,Release/.deps}
|
||||||
|
|
||||||
|
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 [
|
||||||
|
exiftool
|
||||||
|
jellyfin-ffmpeg
|
||||||
|
perl # exiftool-vendored checks for Perl even if exiftool comes from $PATH
|
||||||
|
]
|
||||||
|
}"
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
tests = {
|
||||||
|
inherit (nixosTests) immich;
|
||||||
|
};
|
||||||
|
|
||||||
|
machine-learning = immich-machine-learning;
|
||||||
|
|
||||||
|
inherit
|
||||||
|
src
|
||||||
|
sources
|
||||||
|
web
|
||||||
|
geodata
|
||||||
|
;
|
||||||
|
updateScript = ./update.sh;
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
changelog = "https://github.com/immich-app/immich/releases/tag/${src.tag}";
|
||||||
|
description = "Self-hosted photo and video backup solution";
|
||||||
|
homepage = "https://immich.app/";
|
||||||
|
license = with lib.licenses; [
|
||||||
|
agpl3Only
|
||||||
|
cc-by-40 # geonames
|
||||||
|
];
|
||||||
|
maintainers = with lib.maintainers; [
|
||||||
|
dotlambda
|
||||||
|
jvanbruegge
|
||||||
|
Scrumplex
|
||||||
|
titaniumtown
|
||||||
|
];
|
||||||
|
platforms = lib.platforms.linux ++ lib.platforms.freebsd;
|
||||||
|
mainProgram = "server";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"version": "1.137.3",
|
||||||
|
"hash": "sha256-oKDIx63LayDWhd4uE16rqFWmmwwSWUsUvgZKsgE3KWg=",
|
||||||
|
"components": {
|
||||||
|
"cli": {
|
||||||
|
"npmDepsHash": "sha256-Cjk95tsQM89LkMq6H3B5WYdYrMi3hB6d1XpN2xhHv2U=",
|
||||||
|
"version": "2.2.77"
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"npmDepsHash": "sha256-CvczIXE3Z3LwZezG7kbfJqg2fak2BRXTr0op1Jo1LIg=",
|
||||||
|
"version": "1.137.3"
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"npmDepsHash": "sha256-PcNgD/JFt3221Qgi54XzQZNa53iw3BUe31DM8k+nz/4=",
|
||||||
|
"version": "1.137.3"
|
||||||
|
},
|
||||||
|
"open-api/typescript-sdk": {
|
||||||
|
"npmDepsHash": "sha256-M4ahH6ZP0E3wEgK4VLqSsNjhMFNVTMeRFdzU9EO53vE=",
|
||||||
|
"version": "1.137.3"
|
||||||
|
},
|
||||||
|
"geonames": {
|
||||||
|
"timestamp": "20250725064853",
|
||||||
|
"hash": "sha256-UzP8JapHTCpk5/6X5usLLXQUfqEOUgkq76CTIBZoz08="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i bash -p curl jq prefetch-npm-deps nix-prefetch-github coreutils ripgrep
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
old_version=$(jq -r ".version" sources.json || echo -n "0.0.1")
|
||||||
|
version=$(curl -s "https://api.github.com/repos/immich-app/immich/releases/latest" | jq -r ".tag_name")
|
||||||
|
version="${version#v}"
|
||||||
|
|
||||||
|
echo "Updating to $version"
|
||||||
|
|
||||||
|
if [[ "$old_version" == "$version" ]]; then
|
||||||
|
echo "Already up to date!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Fetching src"
|
||||||
|
src_hash=$(nix-prefetch-github immich-app immich --rev "v${version}" | jq -r .hash)
|
||||||
|
upstream_src="https://raw.githubusercontent.com/immich-app/immich/v$version"
|
||||||
|
|
||||||
|
sources_tmp="$(mktemp)"
|
||||||
|
cat <<EOF > "$sources_tmp"
|
||||||
|
{
|
||||||
|
"version": "$version",
|
||||||
|
"hash": "$src_hash",
|
||||||
|
"components": {}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
lock=$(mktemp)
|
||||||
|
for npm_component in cli server web "open-api/typescript-sdk"; do
|
||||||
|
echo "fetching $npm_component"
|
||||||
|
curl -s -o "$lock" "$upstream_src/$npm_component/package-lock.json"
|
||||||
|
hash=$(prefetch-npm-deps "$lock")
|
||||||
|
echo "$(jq --arg npm_component "$npm_component" \
|
||||||
|
--arg hash "$hash" \
|
||||||
|
--arg version "$(jq -r '.version' <"$lock")" \
|
||||||
|
'.components += {($npm_component): {npmDepsHash: $hash, version: $version}}' \
|
||||||
|
"$sources_tmp")" > "$sources_tmp"
|
||||||
|
done
|
||||||
|
rm "$lock"
|
||||||
|
|
||||||
|
url="http://download.geonames.org/export/dump"
|
||||||
|
curl -s "http://web.archive.org/save/$url/cities500.zip"
|
||||||
|
curl -s "http://web.archive.org/save/$url/admin1CodesASCII.txt"
|
||||||
|
curl -s "http://web.archive.org/save/$url/admin1Codes.txt"
|
||||||
|
timestamp=$(curl -s \
|
||||||
|
"http://archive.org/wayback/available?url=$url/cities500.zip" \
|
||||||
|
| jq -r ".archived_snapshots.closest.timestamp")
|
||||||
|
echo "$(jq --arg timestamp "$timestamp" --arg hash "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" \
|
||||||
|
'.components += {geonames: {timestamp: $timestamp, hash: $hash}}' \
|
||||||
|
"$sources_tmp")" > "$sources_tmp"
|
||||||
|
|
||||||
|
cp "$sources_tmp" sources.json
|
||||||
|
set +o pipefail
|
||||||
|
output="$(nix-build ../../../.. -A immich.geodata 2>&1 || true)"
|
||||||
|
set -o pipefail
|
||||||
|
hash=$(echo "$output" | rg 'got:\s+(sha256-.*)$' -or '$1')
|
||||||
|
echo "$(jq --arg hash "$hash" '.components.geonames.hash = $hash' "$sources_tmp")" > "$sources_tmp"
|
||||||
|
|
||||||
|
mv "$sources_tmp" sources.json
|
||||||
Reference in New Issue
Block a user