Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

photoprism: init at 220302-0059f429 #170953

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions pkgs/development/node-packages/node-packages.json
Expand Up @@ -229,6 +229,7 @@
, "patch-package"
, "peerflix"
, "peerflix-server"
, {"photoprism-frontend": "../../servers/photoprism"}
, "pkg"
, "pm2"
, "pnpm"
Expand Down
4,138 changes: 3,662 additions & 476 deletions pkgs/development/node-packages/node-packages.nix

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pkgs/development/node-packages/overrides.nix
Expand Up @@ -285,6 +285,10 @@ final: prev: {
'';
};

photoprism-frontend = prev."photoprism-frontend-../../servers/photoprism".override {
meta.broken = true; # use the top-level package instead
};

pnpm = prev.pnpm.override {
nativeBuildInputs = [ pkgs.makeWrapper ];

Expand Down
32 changes: 32 additions & 0 deletions pkgs/servers/photoprism/backend.nix
@@ -0,0 +1,32 @@
{ lib, buildGoModule, coreutils, libtensorflow, src, version, ... }:

buildGoModule rec {
inherit src version;
pname = "photoprism-backend";

buildInputs = [
coreutils
libtensorflow
];

postPatch = ''
substituteInPlace internal/commands/passwd.go --replace '/bin/stty' "${coreutils}/bin/stty"
'';

vendorSha256 = "sha256-GaMV1SFDTCgZMZz0lYAKqqqX5zW+pU39vnwtlz2UDbQ=";

subPackages = [ "cmd/photoprism" ];

# https://github.com/mattn/go-sqlite3/issues/822
CGO_CFLAGS = "-Wno-return-local-addr";

# https://github.com/tensorflow/tensorflow/issues/43847
CGO_LDFLAGS = "-fuse-ld=gold";

meta = with lib; {
homepage = "https://photoprism.app";
description = "Photoprism's backend";
license = licenses.agpl3Only;
maintainers = with maintainers; [ misterio77 ];
};
}
Misterio77 marked this conversation as resolved.
Show resolved Hide resolved
79 changes: 79 additions & 0 deletions pkgs/servers/photoprism/default.nix
@@ -0,0 +1,79 @@
{ pkgs, lib, stdenv, fetchFromGitHub, fetchzip, darktable, rawtherapee, ffmpeg, libheif, exiftool, nixosTests }:

let
version = "220302-0059f429";
pname = "photoprism";

src = fetchFromGitHub {
owner = pname;
repo = pname;
rev = version;
sha256 = "sha256-hEA2E5ty9j9BH7DviYh5meao0ot0alPgMoJcplJDRc4=";
};

libtensorflow = pkgs.callPackage ./libtensorflow.nix { };
backend = pkgs.callPackage ./backend.nix { inherit libtensorflow src version; };
frontend = pkgs.callPackage ./frontend.nix { inherit src version; };

fetchModel = { name, sha256 }:
fetchzip {
inherit sha256;
url = "https://dl.photoprism.org/tensorflow/${name}.zip";
stripRoot = false;
};

facenet = fetchModel {
name = "facenet";
sha256 = "sha256-aS5kkNhxOLSLTH/ipxg7NAa1w9X8iiG78jmloR1hpRo=";
};

nasnet = fetchModel {
name = "nasnet";
sha256 = "sha256-bF25jPmZLyeSWy/CGXZE/VE2UupEG2q9Jmr0+1rUYWE=";
};

nsfw = fetchModel {
name = "nsfw";
sha256 = "sha256-zy/HcmgaHOY7FfJUY6I/yjjsMPHR2Ote9ppwqemBlfg=";
};
in
stdenv.mkDerivation {
inherit pname version;

buildInputs = [
darktable
rawtherapee
ffmpeg
libheif
exiftool
Comment on lines +44 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these used? Do we need to put them in $PATH using makeWrapper instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are all runtime deps. Should we make a wrapper instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I don't see how buildInputs would work.

];

dontUnpack = true;
dontBuild = true;

installPhase = ''
runHook preInstall

mkdir -p $out/{bin,assets}
# install backend
ln -s ${backend}/bin/photoprism $out/bin/photoprism
# install frontend
ln -r ${frontend}/assets $out/
# install tensorflow models
ln -r ${nasnet}/nasnet $out/assets
ln -r ${nsfw}/nsfw $out/assets
ln -r ${facenet}/facenet $out/assets

runHook postInstall
'';

passthru.tests.photoprism = nixosTests.photoprism;

meta = with lib; {
homepage = "https://photoprism.app";
description = "Personal Photo Management powered by Go and Google TensorFlow";
inherit (libtensorflow.meta) platforms;
license = licenses.agpl3Only;
maintainers = with maintainers; [ misterio77 ];
};
}
46 changes: 46 additions & 0 deletions pkgs/servers/photoprism/frontend.nix
@@ -0,0 +1,46 @@
{ lib, nodePackages, nodejs-14_x, stdenv, src, version, ... }:

let
nodeDependencies = nodePackages.photoprism-frontend.override {
inherit version;
name = "photoprism-frontend-dependencies";

# Workaround for lack of sourceRoot option in buildNodePackage.
src = "${src}/frontend";

meta.broken = false;
};
in
stdenv.mkDerivation {
inherit src version;
pname = "photoprism-frontend";

buildInputs = [ nodejs-14_x ];

buildPhase = ''
runHook preBuild

pushd frontend
ln -s ${nodeDependencies}/lib/node_modules/photoprism/node_modules ./node_modules
export PATH="${nodeDependencies}/lib/node_modules/photoprism/node_modules/.bin:$PATH"
NODE_ENV=production npm run build
popd

runHook postBuild
'';

installPhase = ''
runHook preInstall

install -Dt $out/assets

runHook postInstall
'';

meta = with lib; {
homepage = "https://photoprism.app";
description = "Photoprism's frontend";
license = licenses.agpl3Only;
maintainers = with maintainers; [ misterio77 ];
};
}
Misterio77 marked this conversation as resolved.
Show resolved Hide resolved
85 changes: 85 additions & 0 deletions pkgs/servers/photoprism/libtensorflow.nix
@@ -0,0 +1,85 @@
{ lib, stdenv, fetchurl, ... }:
let
inherit (stdenv.hostPlatform) system;
in
stdenv.mkDerivation rec {
pname = "libtensorflow-photoprism";
version = "1.15.2";

srcs = [
# Photoprism-packaged libtensorflow tarball (with pre-built libs for both arm64 and amd64)
# We need this specific version because of https://github.com/photoprism/photoprism/issues/222
(fetchurl {
sha256 = {
x86_64-linux = "sha256-bZAC3PJxqcjuGM4RcNtzYtkg3FD3SrO5beDsPoKenzc=";
aarch64-linux = "sha256-qnj4vhSWgrk8SIjzIH1/4waMxMsxMUvqdYZPaSaUJRk=";
}.${system};

url = let
systemName = {
x86_64-linux = "amd64";
aarch64-linux = "arm64";
}.${system};
in "https://dl.photoprism.app/tensorflow/${systemName}/libtensorflow-${systemName}-${version}.tar.gz";
})
# Upstream tensorflow tarball (with .h's photoprism's tarball is missing)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we open an upstream issue about that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It really puzzles me how they build it without those .h's, but somehow they do. I wonder if this will be a relevant issue for them (or be closed as "not our issue")?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should at least try to open an issue since it is an issue with PhotoPrism's TensorFlow distribution(?, is that what this is? a fork? idk).

(fetchurl {
url = "https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.15.0.tar.gz";
sha256 = "sha256-3sv9WnCeztNSP1XM+iOTN6h+GrPgAO/aNhfbeeEDTe0=";
})
];

sourceRoot = ".";

unpackPhase = ''
sources=($srcs)

mkdir downstream upstream
tar xf ''${sources[0]} --directory downstream
tar xf ''${sources[1]} --directory upstream

mv downstream/lib .
mv upstream/{include,LICENSE,THIRD_PARTY_TF_C_LICENSES} .
rm -r downstream upstream

cd lib
ln -sT libtensorflow.so{,.1}
ln -sT libtensorflow_framework.so{,.1}
cd ..
'';

# Patch library to use our libc, libstdc++ and others
patchPhase = let
rpath = lib.makeLibraryPath [ stdenv.cc.libc stdenv.cc.cc.lib ];
in ''
chmod -R +w lib
patchelf --set-rpath "${rpath}:$out/lib" lib/libtensorflow.so
patchelf --set-rpath "${rpath}" lib/libtensorflow_framework.so
'';

buildPhase = ''
# Write pkg-config file.
mkdir lib/pkgconfig
cat > lib/pkgconfig/tensorflow.pc << EOF
Name: TensorFlow
Version: ${version}
Description: Library for computation using data flow graphs for scalable machine learning
Requires:
Libs: -L$out/lib -ltensorflow
Cflags: -I$out/include/tensorflow
EOF
'';

installPhase = ''
mkdir -p $out
cp -r LICENSE THIRD_PARTY_TF_C_LICENSES lib include $out
'';

meta = with lib; {
homepage = "https://dl.photoprism.app/tensorflow/";
description = "Libtensorflow version for usage with photoprism backend";
platforms = [ "x86_64-linux" "aarch64-linux" ];
license = licenses.asl20;
maintainers = with maintainers; [ misterio77 ];
};
}
Misterio77 marked this conversation as resolved.
Show resolved Hide resolved
129 changes: 129 additions & 0 deletions pkgs/servers/photoprism/package.json
@@ -0,0 +1,129 @@
{
"name": "photoprism",
"version": "1.0.0",
"description": "PhotoPrism Progressive Web App (PWA)",
"author": "Michael Mayer",
"license": "AGPL-3.0",
"private": true,
"scripts": {
"watch": "webpack --watch",
"build": "webpack --node-env=production",
"trace": "webpack --stats-children",
"lint": "eslint --cache src/ *.js",
"fmt": "eslint --cache --fix src/ *.js .eslintrc.js",
"test": "karma start",
"upgrade": "npm --depth 10 update && npm audit fix",
"acceptance": "testcafe chromium:headless --skip-js-errors --quarantine-mode --selector-timeout 5000 -S -s tests/screenshots tests/acceptance",
"acceptance-firefox": "testcafe firefox:headless --skip-js-errors --quarantine-mode --selector-timeout 5000 -S -s tests/screenshots tests/acceptance",
"acceptance-private": "testcafe chromium:headless --skip-js-errors --quarantine-mode --selector-timeout 5000 -S -s tests/screenshots tests/acceptance-private",
"acceptance-private-firefox": "testcafe firefox:headless --skip-js-errors --quarantine-mode --selector-timeout 5000 -S -s tests/screenshots tests/acceptance-private",
"acceptance-local": "testcafe chromium --selector-timeout 5000 -S -s tests/screenshots tests/acceptance",
"gettext-extract": "gettext-extract --output src/locales/translations.pot $(find src -type f \\( -iname \\*.vue -o -iname \\*.js \\) -not -path src/common/vm.js)",
"gettext-compile": "gettext-compile --output src/locales/translations.json src/locales/*.po"
},
"dependencies": {
"@babel/cli": "^7.16.8",
"@babel/core": "^7.16.10",
"@babel/eslint-parser": "^7.16.5",
"@babel/plugin-proposal-class-properties": "^7.16.7",
"@babel/plugin-proposal-object-rest-spread": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.16.8",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.16.10",
"@babel/register": "^7.16.9",
"@babel/runtime": "^7.16.7",
"@lcdp/offline-plugin": "^5.1.0",
"@vvo/tzdb": "^6.44.0",
"axios": "^0.26.0",
"axios-mock-adapter": "^1.19.0",
"babel-loader": "^8.2.3",
"babel-plugin-istanbul": "^6.1.1",
"browserslist": "^4.19.1",
"chai": "^4.3.4",
"chrome-finder": "^1.0.7",
"core-js": "^3.21.0",
"cross-env": "^7.0.3",
"css-loader": "^6.5.1",
"cssnano": "^5.0.17",
"easygettext": "^2.17.0",
"eslint": "^8.7.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^17.0.0-1",
"eslint-formatter-pretty": "^4.1.0",
"eslint-plugin-html": "^6.2.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier-vue": "^3.1.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^8.3.0",
"eslint-webpack-plugin": "^3.1.1",
"eventsource-polyfill": "^0.9.6",
"file-loader": "^6.2.0",
"file-saver": "^2.0.5",
"hls.js": "^1.1.3",
"i": "^0.3.7",
"karma": "^6.3.11",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-htmlfile-reporter": "^0.3.8",
"karma-mocha": "^2.0.1",
"karma-verbose-reporter": "^0.0.8",
"karma-webpack": "^5.0.0",
"luxon": "^2.3.0",
"maplibre-gl": "^2.1.1",
"material-design-icons-iconfont": "6.1.1",
"mini-css-extract-plugin": "^2.5.3",
"minimist": ">=1.2.5",
"mocha": "^9.0.2",
"node-storage-shim": "^2.0.1",
"photoswipe": "^4.1.3",
"postcss": "^8.4.6",
"postcss-import": "^14.0.2",
"postcss-loader": "^6.2.1",
"postcss-preset-env": "^7.4.1",
"postcss-reporter": "^7.0.5",
"postcss-url": "^10.1.3",
"prettier": "^2.5.1",
"pubsub-js": "^1.9.4",
"regenerator-runtime": "^0.13.9",
"resolve-url-loader": "^5.0.0",
"sass": "^1.48.0",
"sass-loader": "^12.4.0",
"server": "^1.0.37",
"sockette": "^2.0.6",
"style-loader": "^3.3.1",
"svg-url-loader": "^7.1.1",
"tar": "^6.1.11",
"url-loader": "^4.1.1",
"util": "^0.12.4",
"vue": "^2.6.14",
"vue-fullscreen": "^2.5.2",
"vue-gettext": "^2.1.12",
"vue-infinite-scroll": "^2.0.2",
"vue-loader": "^15.9.8",
"vue-loader-plugin": "^1.3.0",
"vue-luxon": "^0.10.0",
"vue-router": "^3.5.2",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.6.14",
"vue2-filters": "^0.14.0",
"vuetify": "^1.5.24",
"webpack": "^5.66.0",
"webpack-bundle-analyzer": "^4.5.0",
"webpack-cli": "^4.9.1",
"webpack-hot-middleware": "^2.25.1",
"webpack-manifest-plugin": "^4.1.1",
"webpack-md5-hash": "^0.0.6",
"webpack-merge": "^5.8.0"
Misterio77 marked this conversation as resolved.
Show resolved Hide resolved
},
"engines": {
"node": ">= 14.0.0",
"npm": ">= 8.0.0",
"yarn": "please use npm"
},
"browserslist": [
"> 1%",
"not ie <= 9",
"last 3 versions"
]
}