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

Changed files
+103 -4
nixos
doc
manual
release-notes
modules
services
tests
+3
nixos/doc/manual/release-notes/rl-2505.section.md
···
- `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:
+72 -4
nixos/modules/services/misc/paperless.nix
···
-
{ config, pkgs, lib, ... }:
+
{ config, options, pkgs, lib, ... }:
let
cfg = config.services.paperless;
···
};
in
{
-
meta.maintainers = with lib.maintainers; [ leona SuperSandro2000 erikarvstedt ];
+
meta.maintainers = with lib.maintainers; [ leona SuperSandro2000 erikarvstedt atemu theuni ];
imports = [
(lib.mkRenamedOptionModule [ "services" "paperless-ng" ] [ "services" "paperless" ])
···
'';
};
};
+
+
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 {
+
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 {
···
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 = {
+
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
nixos/tests/paperless.nix
···
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, ... }: {
···
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")