From 071f3b34e62a7142cd3d3310af2ad7e11fe528d6 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:23 +0100 Subject: [PATCH 1/9] pythonPackages.filemagic: init at 1.6 --- .../python-modules/filemagic/default.nix | 29 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 31 insertions(+) create mode 100644 pkgs/development/python-modules/filemagic/default.nix diff --git a/pkgs/development/python-modules/filemagic/default.nix b/pkgs/development/python-modules/filemagic/default.nix new file mode 100644 index 00000000000..731b83294a8 --- /dev/null +++ b/pkgs/development/python-modules/filemagic/default.nix @@ -0,0 +1,29 @@ +{ stdenv, lib, buildPythonPackage, fetchFromGitHub, file +, isPy3k, mock, unittest2 }: + +buildPythonPackage rec { + pname = "filemagic"; + version = "1.6"; + + # Don't use the PyPI source because it's missing files required for testing + src = fetchFromGitHub { + owner = "aliles"; + repo = "filemagic"; + rev = "138649062f769fb10c256e454a3e94ecfbf3017b"; + sha256 = "1jxf928jjl2v6zv8kdnfqvywdwql1zqkm1v5xn1d5w0qjcg38d4n"; + }; + + postPatch = '' + substituteInPlace magic/api.py --replace "ctypes.util.find_library('magic')" \ + "'${file}/lib/libmagic${stdenv.hostPlatform.extensions.sharedLibrary}'" + ''; + + checkInputs = [ (if isPy3k then mock else unittest2) ]; + + meta = with lib; { + description = "File type identification using libmagic"; + homepage = https://github.com/aliles/filemagic; + license = licenses.asl20; + maintainers = with maintainers; [ earvstedt ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 85c961a40e9..ec543c75597 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -408,6 +408,8 @@ in { fdint = callPackage ../development/python-modules/fdint { }; + filemagic = callPackage ../development/python-modules/filemagic { }; + fuse = callPackage ../development/python-modules/fuse-python { inherit (pkgs) fuse pkgconfig; }; From 72aec3e01c8f54bc0b976e41a696ff0d5a0d6f05 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:24 +0100 Subject: [PATCH 2/9] pythonPackages.langdetect: init at 1.0.7 --- .../python-modules/langdetect/default.nix | 21 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 23 insertions(+) create mode 100644 pkgs/development/python-modules/langdetect/default.nix diff --git a/pkgs/development/python-modules/langdetect/default.nix b/pkgs/development/python-modules/langdetect/default.nix new file mode 100644 index 00000000000..dcd90dd89bd --- /dev/null +++ b/pkgs/development/python-modules/langdetect/default.nix @@ -0,0 +1,21 @@ +{ lib, buildPythonPackage, fetchPypi, six }: + +buildPythonPackage rec { + pname = "langdetect"; + version = "1.0.7"; + + src = fetchPypi { + inherit pname version; + extension = "zip"; + sha256 = "0c5zm6c7xzsigbb9c7v4r33fcpz911zscfwvh3dq1qxdy3ap18ci"; + }; + + propagatedBuildInputs = [ six ]; + + meta = with lib; { + description = "Python port of Google's language-detection library"; + homepage = https://github.com/Mimino666/langdetect; + license = licenses.asl20; + maintainers = with maintainers; [ earvstedt ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index ec543c75597..69b3061577e 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -484,6 +484,8 @@ in { mpi = pkgs.openmpi; }; + langdetect = callPackage ../development/python-modules/langdetect { }; + libmr = callPackage ../development/python-modules/libmr { }; limitlessled = callPackage ../development/python-modules/limitlessled { }; From 5e3e440a60ae159ccd0d6a7196ed0444c439abe4 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:25 +0100 Subject: [PATCH 3/9] pythonPackages.python-dotenv: init at 0.10.1 --- .../python-modules/python-dotenv/default.nix | 20 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 22 insertions(+) create mode 100644 pkgs/development/python-modules/python-dotenv/default.nix diff --git a/pkgs/development/python-modules/python-dotenv/default.nix b/pkgs/development/python-modules/python-dotenv/default.nix new file mode 100644 index 00000000000..37c7d0dae68 --- /dev/null +++ b/pkgs/development/python-modules/python-dotenv/default.nix @@ -0,0 +1,20 @@ +{ lib, buildPythonPackage, fetchPypi, click, ipython }: + +buildPythonPackage rec { + pname = "python-dotenv"; + version = "0.10.1"; + + src = fetchPypi { + inherit pname version; + sha256 = "1q4sp6ppjiqlsz3h43q9iya4n3qkhx6ng16bcbacfxdyrp9xvcf9"; + }; + + checkInputs = [ click ipython ]; + + meta = with lib; { + description = "Add .env support to your django/flask apps in development and deployments"; + homepage = https://github.com/theskumar/python-dotenv; + license = licenses.bsdOriginal; + maintainers = with maintainers; [ earvstedt ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 69b3061577e..9fa35611270 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -775,6 +775,8 @@ in { python-dbusmock = callPackage ../development/python-modules/python-dbusmock { }; + python-dotenv = callPackage ../development/python-modules/python-dotenv { }; + python-engineio = callPackage ../development/python-modules/python-engineio { }; python-hosts = callPackage ../development/python-modules/python-hosts { }; From 8646d2a2bb0bad76399dd7d29763836df27d7b16 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:26 +0100 Subject: [PATCH 4/9] pythonPackages.pytest-env: init at 0.6.2 --- .../python-modules/pytest-env/default.nix | 20 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 22 insertions(+) create mode 100644 pkgs/development/python-modules/pytest-env/default.nix diff --git a/pkgs/development/python-modules/pytest-env/default.nix b/pkgs/development/python-modules/pytest-env/default.nix new file mode 100644 index 00000000000..909a193bd7b --- /dev/null +++ b/pkgs/development/python-modules/pytest-env/default.nix @@ -0,0 +1,20 @@ +{ lib, buildPythonPackage, fetchPypi, pytest }: + +buildPythonPackage rec { + pname = "pytest-env"; + version = "0.6.2"; + + src = fetchPypi { + inherit pname version; + sha256 = "1hl0ln0cicdid4qjk7mv90lw9xkb0v71dlj7q7rn89vzxxm9b53y"; + }; + + checkInputs = [ pytest ]; + + meta = with lib; { + description = "Pytest plugin used to set environment variables"; + homepage = https://github.com/MobileDynasty/pytest-env; + license = licenses.mit; + maintainers = with maintainers; [ earvstedt ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 9fa35611270..50320973698 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -765,6 +765,8 @@ in { pytest-click = callPackage ../development/python-modules/pytest-click { }; + pytest-env = callPackage ../development/python-modules/pytest-env { }; + pytest-mypy = callPackage ../development/python-modules/pytest-mypy { }; pytest-pylint = callPackage ../development/python-modules/pytest-pylint { }; From 0babb25bb3b4d6209bc81e30a59b67171ccae096 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:27 +0100 Subject: [PATCH 5/9] pythonPackages.pdftotext: init at 2.1.1 --- .../python-modules/pdftotext/default.nix | 20 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 22 insertions(+) create mode 100644 pkgs/development/python-modules/pdftotext/default.nix diff --git a/pkgs/development/python-modules/pdftotext/default.nix b/pkgs/development/python-modules/pdftotext/default.nix new file mode 100644 index 00000000000..6c3b1c0cb92 --- /dev/null +++ b/pkgs/development/python-modules/pdftotext/default.nix @@ -0,0 +1,20 @@ +{ lib, buildPythonPackage, fetchPypi, poppler }: + +buildPythonPackage rec { + pname = "pdftotext"; + version = "2.1.1"; + + src = fetchPypi { + inherit pname version; + sha256 = "1jwc2zpss0983wqqi0kpichasljsxar9c4ma8vycn8maw3pi3bg3"; + }; + + buildInputs = [ poppler ]; + + meta = with lib; { + description = "Simple PDF text extraction"; + homepage = https://github.com/jalan/pdftotext; + license = licenses.mit; + maintainers = with maintainers; [ earvstedt ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 50320973698..ad7f47b0cca 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -582,6 +582,8 @@ in { pdfminer = callPackage ../development/python-modules/pdfminer_six { }; + pdftotext = callPackage ../development/python-modules/pdftotext { }; + pdfx = callPackage ../development/python-modules/pdfx { }; perf = callPackage ../development/python-modules/perf { }; From e401666503082a1ba4dd73f35c3fbbbdca783a26 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:28 +0100 Subject: [PATCH 6/9] pythonPackages.inotify-simple: init at 1.1.8 --- .../python-modules/inotify-simple/default.nix | 22 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 24 insertions(+) create mode 100644 pkgs/development/python-modules/inotify-simple/default.nix diff --git a/pkgs/development/python-modules/inotify-simple/default.nix b/pkgs/development/python-modules/inotify-simple/default.nix new file mode 100644 index 00000000000..2d5e9d78094 --- /dev/null +++ b/pkgs/development/python-modules/inotify-simple/default.nix @@ -0,0 +1,22 @@ +{ lib, buildPythonPackage, fetchPypi }: + +buildPythonPackage rec { + pname = "inotify-simple"; + version = "1.1.8"; + + src = fetchPypi { + pname = "inotify_simple"; + inherit version; + sha256 = "1pfqvnynwh318cakldhg7535kbs02asjsgv6s0ki12i7fgfi0b7w"; + }; + + # The package has no tests + doCheck = false; + + meta = with lib; { + description = "A simple Python wrapper around inotify"; + homepage = https://github.com/chrisjbillington/inotify_simple; + license = licenses.bsd2; + maintainers = with maintainers; [ earvstedt ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index ad7f47b0cca..f1d0fc6200d 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -472,6 +472,8 @@ in { imutils = callPackage ../development/python-modules/imutils { }; + inotify-simple = callPackage ../development/python-modules/inotify-simple { }; + intake = callPackage ../development/python-modules/intake { }; intelhex = callPackage ../development/python-modules/intelhex { }; From 76218fdc3a021940ad0acafd1547e61bd3c2c07b Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:29 +0100 Subject: [PATCH 7/9] pythonPackages.djangoql: init at 0.12.6 --- .../python-modules/djangoql/default.nix | 28 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 30 insertions(+) create mode 100644 pkgs/development/python-modules/djangoql/default.nix diff --git a/pkgs/development/python-modules/djangoql/default.nix b/pkgs/development/python-modules/djangoql/default.nix new file mode 100644 index 00000000000..98f9c04c09f --- /dev/null +++ b/pkgs/development/python-modules/djangoql/default.nix @@ -0,0 +1,28 @@ +{ lib, buildPythonPackage, fetchPypi, python +, django, ply }: + +buildPythonPackage rec { + pname = "djangoql"; + version = "0.12.6"; + + src = fetchPypi { + inherit pname version; + sha256 = "1mwv1ljznj9mn74ncvcyfmj6ygs8xm2rajpxm88gcac9hhdmk5gs"; + }; + + propagatedBuildInputs = [ ply ]; + + checkInputs = [ django ]; + + checkPhase = '' + export PYTHONPATH=test_project:$PYTHONPATH + ${python.executable} test_project/manage.py test core.tests + ''; + + meta = with lib; { + description = "Advanced search language for Django"; + homepage = https://github.com/ivelum/djangoql; + license = licenses.mit; + maintainers = with maintainers; [ earvstedt ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index f1d0fc6200d..4991c12da11 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -2489,6 +2489,8 @@ in { django_pipeline = callPackage ../development/python-modules/django-pipeline { }; + djangoql = callPackage ../development/python-modules/djangoql { }; + dj-database-url = callPackage ../development/python-modules/dj-database-url { }; dj-email-url = callPackage ../development/python-modules/dj-email-url { }; From 0231273a5768fe587f5980581c93e097b030c7b0 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:30 +0100 Subject: [PATCH 8/9] paperless: init at 2.7.0 --- .../applications/office/paperless/default.nix | 170 ++++++++++++++++++ .../python-modules/django-crispy-forms.nix | 36 ++++ .../python-modules/django-filter.nix | 26 +++ .../office/paperless/withConfig.nix | 68 +++++++ pkgs/top-level/all-packages.nix | 2 + 5 files changed, 302 insertions(+) create mode 100644 pkgs/applications/office/paperless/default.nix create mode 100644 pkgs/applications/office/paperless/python-modules/django-crispy-forms.nix create mode 100644 pkgs/applications/office/paperless/python-modules/django-filter.nix create mode 100644 pkgs/applications/office/paperless/withConfig.nix diff --git a/pkgs/applications/office/paperless/default.nix b/pkgs/applications/office/paperless/default.nix new file mode 100644 index 00000000000..0b6ae285bc0 --- /dev/null +++ b/pkgs/applications/office/paperless/default.nix @@ -0,0 +1,170 @@ +{ stdenv +, lib +, fetchFromGitHub +, makeWrapper +, callPackage + +, python3 +, file +, imagemagick7 +, ghostscript +, optipng +, poppler +, tesseract +, unpaper +}: + +## Usage + +# ${paperless}/bin/paperless wraps manage.py + +# ${paperless}/share/paperless/setup-env.sh can be sourced from a +# shell script to setup a Paperless environment + +# paperless.withConfig is a convenience function to setup a +# configured Paperless instance. (See ./withConfig.nix) + +# For WSGI with gunicorn, use a shell script like this: +# let +# pythonEnv = paperless.python.withPackages (ps: paperless.runtimePackages ++ [ ps.gunicorn ]); +# in +# writers.writeBash "run-gunicorn" '' +# source ${paperless}/share/paperless/setup-env.sh +# PYTHONPATH=$paperlessSrc ${pythonEnv}/bin/gunicorn paperless.wsgi +# '' + +let + paperless = stdenv.mkDerivation rec { + name = "paperless-${version}"; + version = "2.7.0"; + + src = fetchFromGitHub { + owner = "the-paperless-project"; + repo = "paperless"; + rev = version; + sha256 = "0pkmyky1crjnsg7r0gfk0fadisfsgzlsq6afpz16wx4hp6yvkkf7"; + }; + + nativeBuildInputs = [ makeWrapper ]; + + doCheck = true; + dontInstall = true; + + pythonEnv = python.withPackages (_: runtimePackages); + pythonCheckEnv = python.withPackages (_: (runtimePackages ++ checkPackages)); + + unpackPhase = '' + srcDir=$out/share/paperless + mkdir -p $srcDir + cp -r --no-preserve=mode $src/src/* $src/LICENSE $srcDir + ''; + + buildPhase = let + # Paperless has explicit runtime checks that expect these binaries to be in PATH + extraBin = lib.makeBinPath [ imagemagick7 ghostscript optipng tesseract unpaper ]; + in '' + ${python.interpreter} -m compileall $srcDir + + makeWrapper $pythonEnv/bin/python $out/bin/paperless \ + --set PATH ${extraBin} --add-flags $out/share/paperless/manage.py + + # A shell snippet that can be sourced to setup a paperless env + cat > $out/share/paperless/setup-env.sh < {}).paperless.withConfig { +# dataDir = /tmp/paperless-data; +# config = { +# PAPERLESS_DISABLE_LOGIN = "true"; +# }; +# }' +# +# Setup DB +# ./paperless migrate +# +# Consume documents in ${dataDir}/consume +# ./paperless document_consumer --oneshot +# +# Start web interface +# ./paperless runserver --noreload localhost:8000 + +{ config ? {}, dataDir ? null, ocrLanguages ? null +, paperlessPkg ? paperless, extraCmds ? "" }: +with lib; +let + paperless = if ocrLanguages == null then + paperlessPkg + else + (paperlessPkg.override { + tesseract = paperlessPkg.tesseract.override { + enableLanguages = ocrLanguages; + }; + }).overrideDerivation (_: { + # `ocrLanguages` might be missing some languages required by the tests. + doCheck = false; + }); + + envVars = (optionalAttrs (dataDir != null) { + PAPERLESS_CONSUMPTION_DIR = "${dataDir}/consume"; + PAPERLESS_MEDIADIR = "${dataDir}/media"; + PAPERLESS_STATICDIR = "${dataDir}/static"; + PAPERLESS_DBDIR = "${dataDir}"; + }) // config; + + envVarDefs = mapAttrsToList (n: v: ''export ${n}="${toString v}"'') envVars; + setupEnvVars = builtins.concatStringsSep "\n" envVarDefs; + + setupEnv = '' + source ${paperless}/share/paperless/setup-env.sh + ${setupEnvVars} + ${optionalString (dataDir != null) '' + mkdir -p "$PAPERLESS_CONSUMPTION_DIR" \ + "$PAPERLESS_MEDIADIR" \ + "$PAPERLESS_STATICDIR" \ + "$PAPERLESS_DBDIR" + ''} + ''; + + runPaperless = writers.writeBash "paperless" '' + set -e + ${setupEnv} + ${extraCmds} + exec python $paperlessSrc/manage.py "$@" + ''; +in + runPaperless // { + inherit paperless setupEnv; + } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index fb1fa5e5ebc..99fa10eb673 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -4952,6 +4952,8 @@ in paper-gtk-theme = callPackage ../misc/themes/paper { }; + paperless = callPackage ../applications/office/paperless { }; + paperwork = callPackage ../applications/office/paperwork { }; papertrail = callPackage ../tools/text/papertrail { }; From 80c3ddbad8144b0d8d4327bf7fd10201b29bb4af Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sun, 27 Jan 2019 15:26:31 +0100 Subject: [PATCH 9/9] paperless service: init --- nixos/modules/misc/ids.nix | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/services/misc/paperless.nix | 185 ++++++++++++++++++++++ nixos/tests/all-tests.nix | 1 + nixos/tests/paperless.nix | 29 ++++ 5 files changed, 218 insertions(+) create mode 100644 nixos/modules/services/misc/paperless.nix create mode 100644 nixos/tests/paperless.nix diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index e78673514e3..73086745038 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -339,6 +339,7 @@ rss2email = 312; cockroachdb = 313; zoneminder = 314; + paperless = 315; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -638,6 +639,7 @@ rss2email = 312; cockroachdb = 313; zoneminder = 314; + paperless = 315; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 56c44a43c6e..1a649385451 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -436,6 +436,7 @@ ./services/misc/octoprint.nix ./services/misc/osrm.nix ./services/misc/packagekit.nix + ./services/misc/paperless.nix ./services/misc/parsoid.nix ./services/misc/phd.nix ./services/misc/plex.nix diff --git a/nixos/modules/services/misc/paperless.nix b/nixos/modules/services/misc/paperless.nix new file mode 100644 index 00000000000..4e6cd80e242 --- /dev/null +++ b/nixos/modules/services/misc/paperless.nix @@ -0,0 +1,185 @@ +{ config, pkgs, lib, ... }: + +with lib; +let + cfg = config.services.paperless; + + defaultUser = "paperless"; + + manage = cfg.package.withConfig { + config = { + PAPERLESS_CONSUMPTION_DIR = cfg.consumptionDir; + PAPERLESS_INLINE_DOC = "true"; + PAPERLESS_DISABLE_LOGIN = "true"; + } // cfg.extraConfig; + inherit (cfg) dataDir ocrLanguages; + paperlessPkg = cfg.package; + }; +in +{ + options.services.paperless = { + enable = mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable Paperless. + + When started, the Paperless database is automatically created if it doesn't + exist and updated if the Paperless package has changed. + Both tasks are achieved by running a Django migration. + ''; + }; + + dataDir = mkOption { + type = types.str; + default = "/var/lib/paperless"; + description = "Directory to store the Paperless data."; + }; + + consumptionDir = mkOption { + type = types.str; + default = "${cfg.dataDir}/consume"; + defaultText = "\${dataDir}/consume"; + description = "Directory from which new documents are imported."; + }; + + consumptionDirIsPublic = mkOption { + type = types.bool; + default = false; + description = "Whether all users can write to the consumption dir."; + }; + + ocrLanguages = mkOption { + type = with types; nullOr (listOf string); + default = null; + description = '' + Languages available for OCR via Tesseract, specified as + ISO 639-2/T language codes. + If unset, defaults to all available languages. + ''; + example = [ "eng" "spa" "jpn" ]; + }; + + address = mkOption { + type = types.str; + default = "localhost"; + description = "Server listening address."; + }; + + port = mkOption { + type = types.int; + default = 28981; + description = "Server port to listen on."; + }; + + extraConfig = mkOption { + type = types.attrs; + default = {}; + description = '' + Extra paperless config options. + + The config values are evaluated as double-quoted Bash string literals. + + See paperless-src/paperless.conf.example for available options. + + To enable user authentication, set PAPERLESS_DISABLE_LOGIN = "false" + and run the shell command $dataDir/paperless-manage createsuperuser. + + To define secret options without storing them in /nix/store, use the following pattern: + PAPERLESS_PASSPHRASE = "$(< /etc/my_passphrase_file)" + ''; + example = literalExample '' + { + PAPERLESS_OCR_LANGUAGE = "deu"; + } + ''; + }; + + user = mkOption { + type = types.str; + default = defaultUser; + description = "User under which Paperless runs."; + }; + + package = mkOption { + type = types.package; + default = pkgs.paperless; + defaultText = "pkgs.paperless"; + description = "The Paperless package to use."; + }; + + manage = mkOption { + type = types.package; + readOnly = true; + default = manage; + description = '' + A script to manage the Paperless instance. + It wraps Django's manage.py and is also available at + $dataDir/manage-paperless + ''; + }; + }; + + config = mkIf cfg.enable { + + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - ${cfg.user} ${cfg.user} - -" + ] ++ (optional cfg.consumptionDirIsPublic + "d '${cfg.consumptionDir}' 777 ${cfg.user} ${cfg.user} - -" + # If the consumption dir is not created here, it's automatically created by + # 'manage' with the default permissions. + ); + + systemd.services.paperless-consumer = { + description = "Paperless document consumer"; + serviceConfig = { + User = cfg.user; + ExecStart = "${manage} document_consumer"; + Restart = "always"; + }; + after = [ "systemd-tmpfiles-setup.service" ]; + wantedBy = [ "multi-user.target" ]; + preStart = '' + if [[ $(readlink ${cfg.dataDir}/paperless-manage) != ${manage} ]]; then + ln -sf ${manage} ${cfg.dataDir}/paperless-manage + fi + + ${manage.setupEnv} + # Auto-migrate on first run or if the package has changed + versionFile="$PAPERLESS_DBDIR/src-version" + if [[ $(cat "$versionFile" 2>/dev/null) != ${cfg.package} ]]; then + python $paperlessSrc/manage.py migrate + echo ${cfg.package} > "$versionFile" + fi + ''; + }; + + systemd.services.paperless-server = { + description = "Paperless document server"; + serviceConfig = { + User = cfg.user; + ExecStart = "${manage} runserver --noreload ${cfg.address}:${toString cfg.port}"; + Restart = "always"; + }; + # Bind to `paperless-consumer` so that the server never runs + # during migrations + bindsTo = [ "paperless-consumer.service" ]; + after = [ "paperless-consumer.service" ]; + wantedBy = [ "multi-user.target" ]; + }; + + users = optionalAttrs (cfg.user == defaultUser) { + users = [{ + name = defaultUser; + group = defaultUser; + uid = config.ids.uids.paperless; + home = cfg.dataDir; + }]; + + groups = [{ + name = defaultUser; + gid = config.ids.gids.paperless; + }]; + }; + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 5639b2668c3..efb0b1c3db8 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -188,6 +188,7 @@ in pam-oath-login = handleTest ./pam-oath-login.nix {}; pam-u2f = handleTest ./pam-u2f.nix {}; pantheon = handleTest ./pantheon.nix {}; + paperless = handleTest ./paperless.nix {}; peerflix = handleTest ./peerflix.nix {}; pgjwt = handleTest ./pgjwt.nix {}; pgmanage = handleTest ./pgmanage.nix {}; diff --git a/nixos/tests/paperless.nix b/nixos/tests/paperless.nix new file mode 100644 index 00000000000..860ad0a6218 --- /dev/null +++ b/nixos/tests/paperless.nix @@ -0,0 +1,29 @@ +import ./make-test.nix ({ lib, ... } : { + name = "paperless"; + meta = with lib.maintainers; { + maintainers = [ earvstedt ]; + }; + + machine = { pkgs, ... }: { + environment.systemPackages = with pkgs; [ imagemagick jq ]; + services.paperless = { + enable = true; + ocrLanguages = [ "eng" ]; + }; + }; + + testScript = '' + $machine->waitForUnit("paperless-consumer.service"); + # Create test doc + $machine->succeed('convert -size 400x40 xc:white -font "DejaVu-Sans" -pointsize 20 -fill black \ + -annotate +5+20 "hello world 16-10-2005" /var/lib/paperless/consume/doc.png'); + + $machine->waitForUnit("paperless-server.service"); + # Wait until server accepts connections + $machine->waitUntilSucceeds("curl -s localhost:28981"); + # Wait until document is consumed + $machine->waitUntilSucceeds('(($(curl -s localhost:28981/api/documents/ | jq .count) == 1))'); + $machine->succeed("curl -s localhost:28981/api/documents/ | jq '.results | .[0] | .created'") + =~ /2005-10-16/ or die; + ''; +})