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

Provide NixOS module option to enable the paperless exporter. #242084

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions nixos/doc/manual/release-notes/rl-2505.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@

- `bind.cacheNetworks` now only controls access for recursive queries, where it previously controlled access for all queries.

- The paperless module now has an option for regular automatic export of
documents data using the integrated document exporter.

- Caddy can now be built with plugins by using `caddy.withPlugins`, a `passthru` function that accepts an attribute set as a parameter. The `plugins` argument represents a list of Caddy plugins, with each Caddy plugin being a versioned module. The `hash` argument represents the `vendorHash` of the resulting Caddy source code with the plugins added.

Example:
Expand Down
76 changes: 72 additions & 4 deletions nixos/modules/services/misc/paperless.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{ config, pkgs, lib, ... }:
{ config, options, pkgs, lib, ... }:
let
cfg = config.services.paperless;

Expand Down Expand Up @@ -82,7 +82,7 @@ let
};
in
{
meta.maintainers = with lib.maintainers; [ leona SuperSandro2000 erikarvstedt ];
meta.maintainers = with lib.maintainers; [ leona SuperSandro2000 erikarvstedt atemu theuni ];
Copy link
Member

Choose a reason for hiding this comment

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

So many maintainers will probably just diverge responsibility and in the end no one feels really responsible.


imports = [
(lib.mkRenamedOptionModule [ "services" "paperless-ng" ] [ "services" "paperless" ])
Expand Down Expand Up @@ -252,9 +252,42 @@ in
'';
};
};

exporter = {
enable = lib.mkEnableOption "regular automatic document exports";

directory = lib.mkOption {
type = lib.types.str;
default = cfg.dataDir + "/export";
defaultText = "\${dataDir}/export";
description = "Directory to store export.";
};

onCalendar = lib.mkOption {
ctheune marked this conversation as resolved.
Show resolved Hide resolved
type = lib.types.nullOr lib.types.str;
default = "01:30:00";
description = ''
When to run the exporter. See {manpage}`systemd.time(7)`.

`null` disables the timer; allowing you to run the
`paperless-exporter` service through other means.
'';
};

settings = lib.mkOption {
type = with lib.types; attrsOf anything;
default = {
"no-progress-bar" = true;
"no-color" = true;
"compare-checksums" = true;
"delete" = true;
};
description = "Settings to pass to the document exporter as CLI arguments.";
};
};
};

config = lib.mkIf cfg.enable {
config = lib.mkIf cfg.enable (lib.mkMerge [ {
services.redis.servers.paperless.enable = lib.mkIf enableRedis true;

services.postgresql = lib.mkIf cfg.database.createLocally {
Expand Down Expand Up @@ -439,5 +472,40 @@ in
gid = config.ids.gids.paperless;
};
};
};
}

(lib.mkIf cfg.exporter.enable {
systemd.tmpfiles.rules = [
"d '${cfg.exporter.directory}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -"
];

services.paperless.exporter.settings = options.services.paperless.exporter.settings.default;

systemd.services.paperless-exporter = {
ctheune marked this conversation as resolved.
Show resolved Hide resolved
startAt = lib.defaultTo [] cfg.exporter.onCalendar;
serviceConfig = {
User = cfg.user;
WorkingDirectory = cfg.dataDir;
};
unitConfig = let
services = [
"paperless-consumer.service"
"paperless-scheduler.service"
"paperless-task-queue.service"
"paperless-web.service" ];
in {
# Shut down the paperless services while the exporter runs
Conflicts = services;
After = services;
# Bring them back up afterwards, regardless of pass/fail
OnFailure = services;
OnSuccess = services;
};
enableStrictShellChecks = true;
script = ''
./paperless-manage document_exporter ${cfg.exporter.directory} ${lib.cli.toGNUCommandLineShell {} cfg.exporter.settings}
'';
};
})
]);
}
28 changes: 28 additions & 0 deletions nixos/tests/paperless.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ import ./make-test-python.nix ({ lib, ... }: {
services.paperless = {
enable = true;
passwordFile = builtins.toFile "password" "admin";

exporter = {
enable = true;

settings = {
"no-color" = lib.mkForce false; # override a default option
"no-thumbnail" = true; # add a new option
};
};
};
};
postgres = { config, pkgs, ... }: {
Expand Down Expand Up @@ -73,6 +82,25 @@ import ./make-test-python.nix ({ lib, ... }: {
metadata = json.loads(node.succeed("curl -u admin:admin -fs localhost:28981/api/documents/3/metadata/"))
assert "original_checksum" in metadata

with subtest("Exporter"):
node.succeed("systemctl start --wait paperless-exporter")
node.wait_for_unit("paperless-web.service")
node.wait_for_unit("paperless-consumer.service")
node.wait_for_unit("paperless-scheduler.service")
node.wait_for_unit("paperless-task-queue.service")

node.succeed("ls -lah /var/lib/paperless/export/manifest.json")

timers = node.succeed("systemctl list-timers paperless-exporter")
print(timers)
assert "paperless-exporter.timer paperless-exporter.service" in timers, "missing timer"
assert "1 timers listed." in timers, "incorrect number of timers"

# Double check that our attrset option override works as expected
cmdline = node.succeed("grep 'paperless-manage' $(systemctl cat paperless-exporter | grep ExecStart | cut -f 2 -d=)")
print(f"Exporter command line {cmdline!r}")
assert cmdline.strip() == "./paperless-manage document_exporter /var/lib/paperless/export --compare-checksums --delete --no-progress-bar --no-thumbnail", "Unexpected exporter command line"

test_paperless(simple)
simple.send_monitor_command("quit")
simple.wait_for_shutdown()
Expand Down