From 05c11f7e28c950f8dba447dfcf2d28381c008e86 Mon Sep 17 00:00:00 2001 From: kilyanni Date: Thu, 7 May 2026 00:54:59 +0200 Subject: [PATCH 1/5] =?UTF-8?q?paperless-ngx:=20rec=20=E2=86=92=20finalAtt?= =?UTF-8?q?rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkgs/by-name/pa/paperless-ngx/package.nix | 56 +++++++++++------------ 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/pkgs/by-name/pa/paperless-ngx/package.nix b/pkgs/by-name/pa/paperless-ngx/package.nix index 084331ade53a..0a5a27b8d686 100644 --- a/pkgs/by-name/pa/paperless-ngx/package.nix +++ b/pkgs/by-name/pa/paperless-ngx/package.nix @@ -31,15 +31,6 @@ let pnpm = pnpm_10; - version = "2.20.15"; - - src = fetchFromGitHub { - owner = "paperless-ngx"; - repo = "paperless-ngx"; - tag = "v${version}"; - hash = "sha256-Czh4Knel0IIHsTc3kEnp1153Kv+3721GRCbTYTkeCDg="; - }; - python = python3.override { self = python; packageOverrides = final: prev: { @@ -73,15 +64,25 @@ let poppler-utils ]; - frontend = stdenv.mkDerivation (finalAttrs: { + nltkDataDir = symlinkJoin { + name = "paperless_ngx_nltk_data"; + paths = with nltk-data; [ + punkt-tab + snowball-data + stopwords + ]; + }; +in +python.pkgs.buildPythonApplication (finalAttrs: let + frontend = stdenv.mkDerivation (feAttrs: { pname = "paperless-ngx-frontend"; - inherit version; + version = finalAttrs.version; - src = src + "/src-ui"; + src = finalAttrs.src + "/src-ui"; pnpmDeps = fetchPnpmDeps { inherit pnpm; - inherit (finalAttrs) pname version src; + inherit (feAttrs) pname version src; fetcherVersion = 3; hash = "sha256-HO+IDNB3NXWgvV0cvZ5zx46JuXv6Tgroz+YfVump5MA="; }; @@ -139,21 +140,18 @@ let runHook postInstall ''; }); - - nltkDataDir = symlinkJoin { - name = "paperless_ngx_nltk_data"; - paths = with nltk-data; [ - punkt-tab - snowball-data - stopwords - ]; - }; -in -python.pkgs.buildPythonApplication rec { +in { pname = "paperless-ngx"; pyproject = true; - inherit version src; + version = "2.20.15"; + + src = fetchFromGitHub { + owner = "paperless-ngx"; + repo = "paperless-ngx"; + tag = "v${finalAttrs.version}"; + hash = "sha256-Czh4Knel0IIHsTc3kEnp1153Kv+3721GRCbTYTkeCDg="; + }; postPatch = '' # pytest-xdist with to many threads makes the tests flaky @@ -266,7 +264,7 @@ python.pkgs.buildPythonApplication rec { installPhase = let - pythonPath = python.pkgs.makePythonPath dependencies; + pythonPath = python.pkgs.makePythonPath finalAttrs.passthru.dependencies; in '' runHook preInstall @@ -319,7 +317,7 @@ python.pkgs.buildPythonApplication rec { export PATH="${path}:$PATH" export HOME=$(mktemp -d) export XDG_DATA_DIRS="${liberation_ttf}/share:$XDG_DATA_DIRS" - export PAPERLESS_NLTK_DIR=${passthru.nltkDataDir} + export PAPERLESS_NLTK_DIR=${finalAttrs.passthru.nltkDataDir} # Limit threads per worker based on NIX_BUILD_CORES, capped at 256 # ocrmypdf has an internal limit of 256 jobs and will fail with more: # https://github.com/ocrmypdf/OCRmyPDF/blob/66308c281306302fac3470f587814c3b212d0c40/src/ocrmypdf/cli.py#L234 @@ -364,7 +362,7 @@ python.pkgs.buildPythonApplication rec { meta = { description = "Tool to scan, index, and archive all of your physical documents"; homepage = "https://docs.paperless-ngx.com/"; - changelog = "https://github.com/paperless-ngx/paperless-ngx/releases/tag/${src.tag}"; + changelog = "https://github.com/paperless-ngx/paperless-ngx/releases/tag/${finalAttrs.src.tag}"; license = lib.licenses.gpl3Only; platforms = lib.platforms.unix; mainProgram = "paperless-ngx"; @@ -374,4 +372,4 @@ python.pkgs.buildPythonApplication rec { erikarvstedt ]; }; -} +}) From e97a92dc4a3a2a48aafa9338ba7772b087c8ba76 Mon Sep 17 00:00:00 2001 From: kilyanni Date: Thu, 7 May 2026 00:55:54 +0200 Subject: [PATCH 2/5] paperless-ngx: make python overrides injectable --- pkgs/by-name/pa/paperless-ngx/package.nix | 36 +++++++++++++---------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/pkgs/by-name/pa/paperless-ngx/package.nix b/pkgs/by-name/pa/paperless-ngx/package.nix index 0a5a27b8d686..aecd4b129ac4 100644 --- a/pkgs/by-name/pa/paperless-ngx/package.nix +++ b/pkgs/by-name/pa/paperless-ngx/package.nix @@ -27,30 +27,36 @@ symlinkJoin, nltk-data, lndir, + extraPythonPackageOverrides ? (_final: _prev: { }), }: let pnpm = pnpm_10; - python = python3.override { - self = python; - packageOverrides = final: prev: { - django = prev.django_5; + defaultPythonPackageOverrides = final: prev: { + django = prev.django_5; - fido2 = prev.fido2.overridePythonAttrs { + fido2 = prev.fido2.overridePythonAttrs { + version = "1.2.0"; + + src = fetchPypi { + pname = "fido2"; version = "1.2.0"; - - src = fetchPypi { - pname = "fido2"; - version = "1.2.0"; - hash = "sha256-45+VkgEi1kKD/aXlWB2VogbnBPpChGv6RmL4aqDTMzs="; - }; - - pytestFlags = [ ]; + hash = "sha256-45+VkgEi1kKD/aXlWB2VogbnBPpChGv6RmL4aqDTMzs="; }; - # tesseract5 may be overwritten in the paperless module and we need to propagate that to make the closure reduction effective - ocrmypdf = prev.ocrmypdf_16.override { tesseract = tesseract5; }; + pytestFlags = [ ]; }; + + # tesseract5 may be overwritten in the paperless module and we need to propagate that to make the closure reduction effective + ocrmypdf = prev.ocrmypdf_16.override { tesseract = tesseract5; }; + }; + + python = python3.override { + self = python; + packageOverrides = lib.composeManyExtensions [ + defaultPythonPackageOverrides + extraPythonPackageOverrides + ]; }; path = lib.makeBinPath [ From 8a2621bf52fae65966e68b28c01b59a24d6008af Mon Sep 17 00:00:00 2001 From: kilyanni Date: Thu, 7 May 2026 00:56:15 +0200 Subject: [PATCH 3/5] paperless-ngx: add nix-update-script --- pkgs/by-name/pa/paperless-ngx/package.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkgs/by-name/pa/paperless-ngx/package.nix b/pkgs/by-name/pa/paperless-ngx/package.nix index aecd4b129ac4..a9be728390f9 100644 --- a/pkgs/by-name/pa/paperless-ngx/package.nix +++ b/pkgs/by-name/pa/paperless-ngx/package.nix @@ -27,6 +27,7 @@ symlinkJoin, nltk-data, lndir, + nix-update-script, extraPythonPackageOverrides ? (_final: _prev: { }), }: let @@ -363,6 +364,12 @@ in { tesseract5 ; tests = { inherit (nixosTests) paperless; }; + updateScript = nix-update-script { + extraArgs = [ + "--subpackage" + "frontend" + ]; + }; }; meta = { From 5a9cb67b6e53a26e2b2dd937769e5573ce89712d Mon Sep 17 00:00:00 2001 From: kilyanni Date: Thu, 7 May 2026 00:57:37 +0200 Subject: [PATCH 4/5] paperless-ngx: factor frontend into separate file --- pkgs/by-name/pa/paperless-ngx/frontend.nix | 88 ++++++++++++++++++++++ pkgs/by-name/pa/paperless-ngx/package.nix | 88 ++-------------------- 2 files changed, 95 insertions(+), 81 deletions(-) create mode 100644 pkgs/by-name/pa/paperless-ngx/frontend.nix diff --git a/pkgs/by-name/pa/paperless-ngx/frontend.nix b/pkgs/by-name/pa/paperless-ngx/frontend.nix new file mode 100644 index 000000000000..20f2843c7793 --- /dev/null +++ b/pkgs/by-name/pa/paperless-ngx/frontend.nix @@ -0,0 +1,88 @@ +{ + stdenv, + lib, + fetchPnpmDeps, + pnpmConfigHook, + pnpm_10, + nodejs, + node-gyp, + pkg-config, + python3, + pango, + giflib, + xcbuild, + src, + version, + meta, +}: +let + pnpm = pnpm_10; +in +stdenv.mkDerivation (finalAttrs: { + pname = "paperless-ngx-frontend"; + inherit version; + + src = src + "/src-ui"; + + pnpmDeps = fetchPnpmDeps { + inherit pnpm; + inherit (finalAttrs) pname version src; + fetcherVersion = 3; + hash = "sha256-HO+IDNB3NXWgvV0cvZ5zx46JuXv6Tgroz+YfVump5MA="; + }; + + nativeBuildInputs = [ + node-gyp + nodejs + pkg-config + pnpmConfigHook + pnpm + python3 + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + xcbuild + ]; + + buildInputs = [ + pango + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + giflib + ]; + + CYPRESS_INSTALL_BINARY = "0"; + NG_CLI_ANALYTICS = "false"; + + buildPhase = '' + runHook preBuild + + pushd node_modules/canvas + node-gyp rebuild + popd + + # cat forcefully disables angular cli's spinner which doesn't work with nix' tty which is 0x0 + pnpm run build --configuration production | cat + + runHook postBuild + ''; + + doCheck = true; + checkPhase = '' + runHook preCheck + + pnpm run test | cat + + runHook postCheck + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/lib/paperless-ui + mv ../src/documents/static/frontend $out/lib/paperless-ui/ + + runHook postInstall + ''; + + inherit meta; +}) diff --git a/pkgs/by-name/pa/paperless-ngx/package.nix b/pkgs/by-name/pa/paperless-ngx/package.nix index a9be728390f9..641da02e2848 100644 --- a/pkgs/by-name/pa/paperless-ngx/package.nix +++ b/pkgs/by-name/pa/paperless-ngx/package.nix @@ -3,12 +3,10 @@ stdenv, fetchFromGitHub, fetchPypi, - node-gyp, - nodejs, + callPackage, nixosTests, gettext, python3, - giflib, ghostscript_headless, imagemagickBig, jbig2enc, @@ -16,14 +14,8 @@ pngquant, qpdf, tesseract5, - fetchPnpmDeps, - pnpmConfigHook, - pnpm_10, poppler-utils, liberation_ttf, - xcbuild, - pango, - pkg-config, symlinkJoin, nltk-data, lndir, @@ -31,8 +23,6 @@ extraPythonPackageOverrides ? (_final: _prev: { }), }: let - pnpm = pnpm_10; - defaultPythonPackageOverrides = final: prev: { django = prev.django_5; @@ -80,74 +70,7 @@ let ]; }; in -python.pkgs.buildPythonApplication (finalAttrs: let - frontend = stdenv.mkDerivation (feAttrs: { - pname = "paperless-ngx-frontend"; - version = finalAttrs.version; - - src = finalAttrs.src + "/src-ui"; - - pnpmDeps = fetchPnpmDeps { - inherit pnpm; - inherit (feAttrs) pname version src; - fetcherVersion = 3; - hash = "sha256-HO+IDNB3NXWgvV0cvZ5zx46JuXv6Tgroz+YfVump5MA="; - }; - - nativeBuildInputs = [ - node-gyp - nodejs - pkg-config - pnpmConfigHook - pnpm - python3 - ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ - xcbuild - ]; - - buildInputs = [ - pango - ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ - giflib - ]; - - CYPRESS_INSTALL_BINARY = "0"; - NG_CLI_ANALYTICS = "false"; - - buildPhase = '' - runHook preBuild - - pushd node_modules/canvas - node-gyp rebuild - popd - - # cat forcefully disables angular cli's spinner which doesn't work with nix' tty which is 0x0 - pnpm run build --configuration production | cat - - runHook postBuild - ''; - - doCheck = true; - checkPhase = '' - runHook preCheck - - pnpm run test | cat - - runHook postCheck - ''; - - installPhase = '' - runHook preInstall - - mkdir -p $out/lib/paperless-ui - mv ../src/documents/static/frontend $out/lib/paperless-ui/ - - runHook postInstall - ''; - }); -in { +python.pkgs.buildPythonApplication (finalAttrs: { pname = "paperless-ngx"; pyproject = true; @@ -278,7 +201,7 @@ in { mkdir -p $out/lib/paperless-ngx/static/frontend cp -r {src,static,LICENSE} $out/lib/paperless-ngx - lndir -silent ${frontend}/lib/paperless-ui/frontend $out/lib/paperless-ngx/static/frontend + lndir -silent ${finalAttrs.passthru.frontend}/lib/paperless-ui/frontend $out/lib/paperless-ngx/static/frontend chmod +x $out/lib/paperless-ngx/src/manage.py makeWrapper $out/lib/paperless-ngx/src/manage.py $out/bin/paperless-ngx \ --prefix PYTHONPATH : "${pythonPath}" \ @@ -356,8 +279,11 @@ in { doCheck = !stdenv.hostPlatform.isDarwin; passthru = { + frontend = callPackage ./frontend.nix { + inherit (finalAttrs) src version; + meta = removeAttrs finalAttrs.meta [ "mainProgram" ]; + }; inherit - frontend nltkDataDir path python From 49951091aad9219dcc6bfc422eb554114efd98e8 Mon Sep 17 00:00:00 2001 From: kilyanni Date: Wed, 1 Jul 2026 18:22:24 +0200 Subject: [PATCH 5/5] nixos/paperless: use package.passthru.dependencies for PYTHONPATH --- nixos/modules/services/misc/paperless.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/services/misc/paperless.nix b/nixos/modules/services/misc/paperless.nix index 9df4e99ff9a5..f7ca6c2717bc 100644 --- a/nixos/modules/services/misc/paperless.nix +++ b/nixos/modules/services/misc/paperless.nix @@ -621,7 +621,7 @@ in PrivateNetwork = false; }; environment = env // { - PYTHONPATH = "${cfg.package.python.pkgs.makePythonPath cfg.package.propagatedBuildInputs}:${cfg.package}/lib/paperless-ngx/src"; + PYTHONPATH = "${cfg.package.python.pkgs.makePythonPath cfg.package.passthru.dependencies}:${cfg.package}/lib/paperless-ngx/src"; }; # Allow the web interface to access the private /tmp directory of the server. # This is required to support uploading files via the web interface.