paperless-ngx: 2.14.7 -> 2.15.1 (#397828)

Changed files
+161 -109
nixos
doc
manual
release-notes
modules
services
pkgs
by-name
pa
paperless-ngx
ta
tandoor-recipes
development
python-modules
channels-redis
drf-spectacular-sidecar
whitenoise
whoosh
whoosh-reloaded
top-level
+2
nixos/doc/manual/release-notes/rl-2505.section.md
···
- `linuxPackages.nvidiaPackages.stable` now defaults to the `production` variant instead of `latest`.
- `timescaledb` requires manual upgrade steps.
After you run ALTER EXTENSION, you must run [this SQL script](https://github.com/timescale/timescaledb-extras/blob/master/utils/2.15.X-fix_hypertable_foreign_keys.sql). For more details, see the following pull requests [#6797](https://github.com/timescale/timescaledb/pull/6797).
PostgreSQL 13 is no longer supported in TimescaleDB v2.16.
···
- `linuxPackages.nvidiaPackages.stable` now defaults to the `production` variant instead of `latest`.
+
- `paperless-ngx` has been updated to minor version 2.15 which switched the web server from Gunicorn to Granian. If you set Gunicorn specific envs (usually contain GUNICORN) they must be updated. Also `services.paperless.address` no longer accepts a domain name and Granian also does not support listening on unix domain sockets.
+
- `timescaledb` requires manual upgrade steps.
After you run ALTER EXTENSION, you must run [this SQL script](https://github.com/timescale/timescaledb-extras/blob/master/utils/2.15.X-fix_hypertable_foreign_keys.sql). For more details, see the following pull requests [#6797](https://github.com/timescale/timescaledb/pull/6797).
PostgreSQL 13 is no longer supported in TimescaleDB v2.16.
+6 -6
nixos/modules/services/misc/paperless.nix
···
PAPERLESS_MEDIA_ROOT = cfg.mediaDir;
PAPERLESS_CONSUMPTION_DIR = cfg.consumptionDir;
PAPERLESS_THUMBNAIL_FONT_NAME = defaultFont;
-
GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}";
}
// lib.optionalAttrs (config.time.timeZone != null) {
PAPERLESS_TIME_ZONE = config.time.timeZone;
···
address = lib.mkOption {
type = lib.types.str;
-
default = "localhost";
description = "Web interface address.";
};
···
echo "PAPERLESS_SECRET_KEY is empty, refusing to start."
exit 1
fi
-
exec ${cfg.package.python.pkgs.gunicorn}/bin/gunicorn \
-
-c ${cfg.package}/lib/paperless-ngx/gunicorn.conf.py paperless.asgi:application
'';
serviceConfig = defaultServiceConfig // {
User = cfg.user;
Restart = "on-failure";
LimitNOFILE = 65536;
-
# gunicorn needs setuid, liblapack needs mbind
-
SystemCallFilter = defaultServiceConfig.SystemCallFilter ++ [ "@setuid mbind" ];
# Needs to serve web page
PrivateNetwork = false;
};
···
PAPERLESS_MEDIA_ROOT = cfg.mediaDir;
PAPERLESS_CONSUMPTION_DIR = cfg.consumptionDir;
PAPERLESS_THUMBNAIL_FONT_NAME = defaultFont;
+
GRANIAN_HOST = cfg.address;
+
GRANIAN_PORT = toString cfg.port;
}
// lib.optionalAttrs (config.time.timeZone != null) {
PAPERLESS_TIME_ZONE = config.time.timeZone;
···
address = lib.mkOption {
type = lib.types.str;
+
default = "127.0.0.1";
description = "Web interface address.";
};
···
echo "PAPERLESS_SECRET_KEY is empty, refusing to start."
exit 1
fi
+
exec ${lib.getExe cfg.package.python.pkgs.granian} --interface asginl --ws "paperless.asgi:application"
'';
serviceConfig = defaultServiceConfig // {
User = cfg.user;
Restart = "on-failure";
LimitNOFILE = 65536;
+
# liblapack needs mbind
+
SystemCallFilter = defaultServiceConfig.SystemCallFilter ++ [ "mbind" ];
# Needs to serve web page
PrivateNetwork = false;
};
+83 -76
pkgs/by-name/pa/paperless-ngx/package.nix
···
lib,
stdenv,
fetchFromGitHub,
-
fetchpatch,
-
buildNpmPackage,
nodejs_20,
nixosTests,
gettext,
···
qpdf,
tesseract5,
unpaper,
poppler-utils,
liberation_ttf,
xcbuild,
···
xorg,
}:
let
-
version = "2.14.7";
src = fetchFromGitHub {
owner = "paperless-ngx";
repo = "paperless-ngx";
tag = "v${version}";
-
hash = "sha256-p3eUEb/ZPK11NbqE4LU+3TE1Xny9sjfYvVVmABkoAEQ=";
};
-
patches = [
-
# Fix frontend tests in March (yes, it's date dependent)
-
(fetchpatch {
-
url = "https://github.com/paperless-ngx/paperless-ngx/commit/bc90ccc5551f184a683128def772652ad74c65e3.patch";
-
hash = "sha256-KArPyKZLi5LfaTDTY3DxA3cdQYYadpQo052Xk9eH14c=";
-
})
-
];
-
# subpath installation is broken with uvicorn >= 0.26
# https://github.com/NixOS/nixpkgs/issues/298719
# https://github.com/paperless-ngx/paperless-ngx/issues/5494
···
# tesseract5 may be overwritten in the paperless module and we need to propagate that to make the closure reduction effective
ocrmypdf = prev.ocrmypdf.override { tesseract = tesseract5; };
-
-
uvicorn = prev.uvicorn.overridePythonAttrs (_: {
-
version = "0.25.0";
-
src = fetchFromGitHub {
-
owner = "encode";
-
repo = "uvicorn";
-
rev = "0.25.0";
-
hash = "sha256-ng98DTw49zyFjrPnEwfnPfONyjKKZYuLl0qduxSppYk=";
-
};
-
});
};
};
···
poppler-utils
];
-
frontend = buildNpmPackage {
-
pname = "paperless-ngx-frontend";
-
inherit version src patches;
-
nodejs = nodejs_20; # does not build with 22
-
postPatch = ''
-
cd src-ui
-
'';
-
npmDepsHash = "sha256-hK7Soop9gBZP4m2UzbEIAsLkPKpbQkLmVruY2So4CSs=";
-
nativeBuildInputs =
-
[
-
pkg-config
-
python3
-
]
-
++ lib.optionals stdenv.hostPlatform.isDarwin [
-
xcbuild
-
];
-
buildInputs =
-
[
-
pango
-
]
-
++ lib.optionals stdenv.hostPlatform.isDarwin [
-
giflib
-
darwin.apple_sdk.frameworks.CoreText
-
];
-
CYPRESS_INSTALL_BINARY = "0";
-
NG_CLI_ANALYTICS = "false";
-
npmBuildFlags = [
-
"--"
-
"--configuration"
-
"production"
-
];
-
doCheck = true;
-
checkPhase = ''
-
runHook preCheck
-
npm run test
-
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 rec {
pname = "paperless-ngx";
-
pyproject = false;
-
inherit version src patches;
postPatch = ''
# pytest-xdist with to many threads makes the tests flaky
if (( $NIX_BUILD_CORES > 4)); then
NIX_BUILD_CORES=4
fi
-
substituteInPlace src/setup.cfg \
-
--replace-fail "--numprocesses auto --maxprocesses=16" "--numprocesses $NIX_BUILD_CORES"
'';
nativeBuildInputs = [
···
xorg.lndir
];
dependencies =
with python.pkgs;
[
···
django-soft-delete
djangorestframework
djangorestframework-guardian2
drf-writable-nested
filelock
flower
gotenberg-client
-
gunicorn
httpx-oauth
imap-tools
inotifyrecursive
···
setproctitle
tika-client
tqdm
-
uvicorn
watchdog
whitenoise
-
whoosh
zxing-cpp
]
++ django-allauth.optional-dependencies.mfa
++ django-allauth.optional-dependencies.socialaccount
-
++ redis.optional-dependencies.hiredis
-
++ uvicorn.optional-dependencies.standard;
postBuild = ''
# Compile manually because `pythonRecompileBytecodeHook` only works
···
runHook preInstall
mkdir -p $out/lib/paperless-ngx/static/frontend
-
cp -r {src,static,LICENSE,gunicorn.conf.py} $out/lib/paperless-ngx
lndir -silent ${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 \
···
lib,
stdenv,
fetchFromGitHub,
+
node-gyp,
nodejs_20,
nixosTests,
gettext,
···
qpdf,
tesseract5,
unpaper,
+
pnpm,
poppler-utils,
liberation_ttf,
xcbuild,
···
xorg,
}:
let
+
version = "2.15.1";
src = fetchFromGitHub {
owner = "paperless-ngx";
repo = "paperless-ngx";
tag = "v${version}";
+
hash = "sha256-vICkRfVxzQlqhSBCieVNSGeXb6FCOx0qOnInKMy6Lhg=";
};
# subpath installation is broken with uvicorn >= 0.26
# https://github.com/NixOS/nixpkgs/issues/298719
# https://github.com/paperless-ngx/paperless-ngx/issues/5494
···
# tesseract5 may be overwritten in the paperless module and we need to propagate that to make the closure reduction effective
ocrmypdf = prev.ocrmypdf.override { tesseract = tesseract5; };
};
};
···
poppler-utils
];
+
frontend =
+
let
+
frontendSrc = src + "/src-ui";
+
in
+
stdenv.mkDerivation rec {
+
pname = "paperless-ngx-frontend";
+
inherit version;
+
src = frontendSrc;
+
pnpmDeps = pnpm.fetchDeps {
+
inherit pname version src;
+
hash = "sha256-yoTXlxXLcWD2DMxqjb02ZORJ+E0xE1DbZm1VL7vXM4g=";
+
};
+
nativeBuildInputs =
+
[
+
node-gyp
+
nodejs_20
+
pkg-config
+
pnpm.configHook
+
python3
+
]
+
++ lib.optionals stdenv.hostPlatform.isDarwin [
+
xcbuild
+
];
+
+
buildInputs =
+
[
+
pango
+
]
+
++ lib.optionals stdenv.hostPlatform.isDarwin [
+
giflib
+
darwin.apple_sdk.frameworks.CoreText
+
];
+
+
CYPRESS_INSTALL_BINARY = "0";
+
NG_CLI_ANALYTICS = "false";
+
+
buildPhase = ''
+
runHook preBuild
+
+
pushd node_modules/canvas
+
node-gyp rebuild
+
popd
+
+
pnpm run build --configuration production
+
+
runHook postBuild
+
'';
+
doCheck = true;
+
checkPhase = ''
+
runHook preCheck
+
pnpm run test
+
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 rec {
pname = "paperless-ngx";
+
pyproject = true;
+
inherit version src;
postPatch = ''
# pytest-xdist with to many threads makes the tests flaky
if (( $NIX_BUILD_CORES > 4)); then
NIX_BUILD_CORES=4
fi
+
substituteInPlace pyproject.toml \
+
--replace-fail '"--numprocesses=auto",' "" \
+
--replace-fail '--maxprocesses=16' "--numprocesses=$NIX_BUILD_CORES" \
+
--replace-fail "djangorestframework-guardian~=0.3.0" "djangorestframework-guardian2"
'';
nativeBuildInputs = [
···
xorg.lndir
];
+
pythonRelaxDeps = [
+
"django-allauth"
+
"drf-spectacular-sidecar"
+
# TODO: https://github.com/NixOS/nixpkgs/pull/373099
+
"zxing-cpp"
+
];
+
dependencies =
with python.pkgs;
[
···
django-soft-delete
djangorestframework
djangorestframework-guardian2
+
drf-spectacular
+
drf-spectacular-sidecar
drf-writable-nested
filelock
flower
gotenberg-client
+
granian
httpx-oauth
imap-tools
inotifyrecursive
···
setproctitle
tika-client
tqdm
watchdog
whitenoise
+
whoosh-reloaded
zxing-cpp
]
++ django-allauth.optional-dependencies.mfa
++ django-allauth.optional-dependencies.socialaccount
+
++ redis.optional-dependencies.hiredis;
postBuild = ''
# Compile manually because `pythonRecompileBytecodeHook` only works
···
runHook preInstall
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
chmod +x $out/lib/paperless-ngx/src/manage.py
makeWrapper $out/lib/paperless-ngx/src/manage.py $out/bin/paperless-ngx \
+6 -1
pkgs/by-name/ta/tandoor-recipes/package.nix
···
];
postPatch = ''
substituteInPlace pytest.ini --subst-var NIX_BUILD_CORES
'';
···
mock
pytestCheckHook
pytest-asyncio
-
pytest-cov
pytest-django
pytest-factoryboy
pytest-html
···
];
postPatch = ''
+
# high parallelism let the tests easily fail with concurrent errors
+
if (( $NIX_BUILD_CORES > 4)); then
+
NIX_BUILD_CORES=4
+
fi
+
substituteInPlace pytest.ini --subst-var NIX_BUILD_CORES
'';
···
mock
pytestCheckHook
pytest-asyncio
+
pytest-cov-stub
pytest-django
pytest-factoryboy
pytest-html
+7 -11
pkgs/development/python-modules/channels-redis/default.nix
···
{
lib,
-
aioredis,
asgiref,
buildPythonPackage,
channels,
cryptography,
fetchFromGitHub,
-
hiredis,
msgpack,
pythonOlder,
redis,
}:
buildPythonPackage rec {
pname = "channels-redis";
-
version = "4.1.0";
-
format = "setuptools";
disabled = pythonOlder "3.7";
···
owner = "django";
repo = "channels_redis";
tag = version;
-
hash = "sha256-Eid9aWlLNnqr3WAnsLe+Pz9gsugCsdDKi0+nFNF02CI=";
};
-
buildInputs = [
-
hiredis
redis
-
];
-
-
propagatedBuildInputs = [
-
aioredis
asgiref
channels
msgpack
···
{
lib,
asgiref,
buildPythonPackage,
channels,
cryptography,
fetchFromGitHub,
msgpack,
pythonOlder,
redis,
+
setuptools,
}:
buildPythonPackage rec {
pname = "channels-redis";
+
version = "4.2.1";
+
pyproject = true;
disabled = pythonOlder "3.7";
···
owner = "django";
repo = "channels_redis";
tag = version;
+
hash = "sha256-jQkpuOQNU2KCWavXSE/n8gdpQhhAafQbZYfbX71Rcds=";
};
+
build-system = [ setuptools ];
+
+
dependencies = [
redis
asgiref
channels
msgpack
+7 -4
pkgs/development/python-modules/drf-spectacular-sidecar/default.nix
···
buildPythonPackage,
fetchFromGitHub,
django,
}:
buildPythonPackage rec {
pname = "drf-spectacular-sidecar";
-
version = "2023.9.1";
-
format = "setuptools";
src = fetchFromGitHub {
owner = "tfranzel";
repo = "drf-spectacular-sidecar";
rev = version;
-
hash = "sha256-EoQKbxzXEuKC50/W1/tBB2wASJZmNNwg9r1qhIB4Ws8=";
};
-
propagatedBuildInputs = [ django ];
# no tests
doCheck = false;
···
buildPythonPackage,
fetchFromGitHub,
django,
+
setuptools,
}:
buildPythonPackage rec {
pname = "drf-spectacular-sidecar";
+
version = "2025.4.1";
+
pyproject = true;
src = fetchFromGitHub {
owner = "tfranzel";
repo = "drf-spectacular-sidecar";
rev = version;
+
hash = "sha256-YzSUwShj7QGCVKlTRM2Gro38Y+jGYQsMGBMAH0radmA=";
};
+
build-system = [ setuptools ];
+
+
dependencies = [ django ];
# no tests
doCheck = false;
+7 -10
pkgs/development/python-modules/whitenoise/default.nix
···
django,
fetchFromGitHub,
pytestCheckHook,
-
pythonOlder,
requests,
setuptools,
}:
buildPythonPackage rec {
pname = "whitenoise";
-
version = "6.7.0";
pyproject = true;
-
disabled = pythonOlder "3.8";
-
-
__darwinAllowLocalNetworking = true;
-
src = fetchFromGitHub {
owner = "evansd";
-
repo = pname;
tag = version;
-
hash = "sha256-4SrTiTqBrfFuQ/8mqQL+YiehFWW+ZzKiAF0h2XyYuSs=";
};
-
nativeBuildInputs = [ setuptools ];
-
propagatedBuildInputs = [ brotli ];
nativeCheckInputs = [
django
pytestCheckHook
requests
];
disabledTestPaths = [
# Don't run Django tests
···
django,
fetchFromGitHub,
pytestCheckHook,
requests,
setuptools,
}:
buildPythonPackage rec {
pname = "whitenoise";
+
version = "6.9.0";
pyproject = true;
src = fetchFromGitHub {
owner = "evansd";
+
repo = "whitenoise";
tag = version;
+
hash = "sha256-UmM8Az22ql3uUpyY6jj7ky3LelmttFBqGMYlzlNRAHg=";
};
+
build-system = [ setuptools ];
+
dependencies = [ brotli ];
nativeCheckInputs = [
django
pytestCheckHook
requests
];
+
+
__darwinAllowLocalNetworking = true;
disabledTestPaths = [
# Don't run Django tests
+40
pkgs/development/python-modules/whoosh-reloaded/default.nix
···
···
+
{
+
lib,
+
buildPythonPackage,
+
cached-property,
+
fetchFromGitHub,
+
loguru,
+
pytestCheckHook,
+
setuptools,
+
}:
+
+
buildPythonPackage rec {
+
pname = "whoosh-reloaded";
+
version = "2.7.5";
+
pyproject = true;
+
+
src = fetchFromGitHub {
+
owner = "Sygil-Dev";
+
repo = "whoosh-reloaded";
+
tag = "v${version}";
+
hash = "sha256-frM8tw298Yz3u3rLK4CxWUXL6ymCSwYyYhXP/EdyjtQ=";
+
};
+
+
build-system = [ setuptools ];
+
+
dependencies = [
+
cached-property
+
loguru
+
];
+
+
nativeCheckInputs = [ pytestCheckHook ];
+
+
pythonImportsCheck = [ "whoosh" ];
+
+
meta = {
+
description = "Fast, featureful full-text indexing and searching library implemented in pure Python";
+
homepage = "https://github.com/Sygil-Dev/whoosh-reloaded";
+
license = lib.licenses.bsd2;
+
maintainers = with lib.maintainers; [ SuperSandro2000 ];
+
};
+
}
+1 -1
pkgs/development/python-modules/whoosh/default.nix
···
hash = "sha256-fKVjPb+p4OD6QA0xUaigxL7FO9Ls7cCmdwWxdWXDGoM=";
};
-
nativeBuildInputs = [ setuptools ];
nativeCheckInputs = [ pytestCheckHook ];
···
hash = "sha256-fKVjPb+p4OD6QA0xUaigxL7FO9Ls7cCmdwWxdWXDGoM=";
};
+
build-system = [ setuptools ];
nativeCheckInputs = [ pytestCheckHook ];
+2
pkgs/top-level/python-packages.nix
···
whoosh = callPackage ../development/python-modules/whoosh { };
widgetsnbextension = callPackage ../development/python-modules/widgetsnbextension { };
widlparser = callPackage ../development/python-modules/widlparser { };
···
whoosh = callPackage ../development/python-modules/whoosh { };
+
whoosh-reloaded = callPackage ../development/python-modules/whoosh-reloaded { };
+
widgetsnbextension = callPackage ../development/python-modules/widgetsnbextension { };
widlparser = callPackage ../development/python-modules/widlparser { };