You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

184 lines
5.3 KiB

  1. { config, pkgs, lib, ... }:
  2. with lib;
  3. let
  4. cfg = config.services.paperless;
  5. defaultUser = "paperless";
  6. manage = cfg.package.withConfig {
  7. config = {
  8. PAPERLESS_CONSUMPTION_DIR = cfg.consumptionDir;
  9. PAPERLESS_INLINE_DOC = "true";
  10. PAPERLESS_DISABLE_LOGIN = "true";
  11. } // cfg.extraConfig;
  12. inherit (cfg) dataDir ocrLanguages;
  13. paperlessPkg = cfg.package;
  14. };
  15. in
  16. {
  17. options.services.paperless = {
  18. enable = mkOption {
  19. type = lib.types.bool;
  20. default = false;
  21. description = ''
  22. Enable Paperless.
  23. When started, the Paperless database is automatically created if it doesn't
  24. exist and updated if the Paperless package has changed.
  25. Both tasks are achieved by running a Django migration.
  26. '';
  27. };
  28. dataDir = mkOption {
  29. type = types.str;
  30. default = "/var/lib/paperless";
  31. description = "Directory to store the Paperless data.";
  32. };
  33. consumptionDir = mkOption {
  34. type = types.str;
  35. default = "${cfg.dataDir}/consume";
  36. defaultText = "\${dataDir}/consume";
  37. description = "Directory from which new documents are imported.";
  38. };
  39. consumptionDirIsPublic = mkOption {
  40. type = types.bool;
  41. default = false;
  42. description = "Whether all users can write to the consumption dir.";
  43. };
  44. ocrLanguages = mkOption {
  45. type = with types; nullOr (listOf str);
  46. default = null;
  47. description = ''
  48. Languages available for OCR via Tesseract, specified as
  49. <literal>ISO 639-2/T</literal> language codes.
  50. If unset, defaults to all available languages.
  51. '';
  52. example = [ "eng" "spa" "jpn" ];
  53. };
  54. address = mkOption {
  55. type = types.str;
  56. default = "localhost";
  57. description = "Server listening address.";
  58. };
  59. port = mkOption {
  60. type = types.int;
  61. default = 28981;
  62. description = "Server port to listen on.";
  63. };
  64. extraConfig = mkOption {
  65. type = types.attrs;
  66. default = {};
  67. description = ''
  68. Extra paperless config options.
  69. The config values are evaluated as double-quoted Bash string literals.
  70. See <literal>paperless-src/paperless.conf.example</literal> for available options.
  71. To enable user authentication, set <literal>PAPERLESS_DISABLE_LOGIN = "false"</literal>
  72. and run the shell command <literal>$dataDir/paperless-manage createsuperuser</literal>.
  73. To define secret options without storing them in /nix/store, use the following pattern:
  74. <literal>PAPERLESS_PASSPHRASE = "$(&lt; /etc/my_passphrase_file)"</literal>
  75. '';
  76. example = literalExample ''
  77. {
  78. PAPERLESS_OCR_LANGUAGE = "deu";
  79. }
  80. '';
  81. };
  82. user = mkOption {
  83. type = types.str;
  84. default = defaultUser;
  85. description = "User under which Paperless runs.";
  86. };
  87. package = mkOption {
  88. type = types.package;
  89. default = pkgs.paperless;
  90. defaultText = "pkgs.paperless";
  91. description = "The Paperless package to use.";
  92. };
  93. manage = mkOption {
  94. type = types.package;
  95. readOnly = true;
  96. default = manage;
  97. description = ''
  98. A script to manage the Paperless instance.
  99. It wraps Django's manage.py and is also available at
  100. <literal>$dataDir/manage-paperless</literal>
  101. '';
  102. };
  103. };
  104. config = mkIf cfg.enable {
  105. systemd.tmpfiles.rules = [
  106. "d '${cfg.dataDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -"
  107. ] ++ (optional cfg.consumptionDirIsPublic
  108. "d '${cfg.consumptionDir}' 777 - - - -"
  109. # If the consumption dir is not created here, it's automatically created by
  110. # 'manage' with the default permissions.
  111. );
  112. systemd.services.paperless-consumer = {
  113. description = "Paperless document consumer";
  114. serviceConfig = {
  115. User = cfg.user;
  116. ExecStart = "${manage} document_consumer";
  117. Restart = "always";
  118. };
  119. after = [ "systemd-tmpfiles-setup.service" ];
  120. wantedBy = [ "multi-user.target" ];
  121. preStart = ''
  122. if [[ $(readlink ${cfg.dataDir}/paperless-manage) != ${manage} ]]; then
  123. ln -sf ${manage} ${cfg.dataDir}/paperless-manage
  124. fi
  125. ${manage.setupEnv}
  126. # Auto-migrate on first run or if the package has changed
  127. versionFile="$PAPERLESS_DBDIR/src-version"
  128. if [[ $(cat "$versionFile" 2>/dev/null) != ${cfg.package} ]]; then
  129. python $paperlessSrc/manage.py migrate
  130. echo ${cfg.package} > "$versionFile"
  131. fi
  132. '';
  133. };
  134. systemd.services.paperless-server = {
  135. description = "Paperless document server";
  136. serviceConfig = {
  137. User = cfg.user;
  138. ExecStart = "${manage} runserver --noreload ${cfg.address}:${toString cfg.port}";
  139. Restart = "always";
  140. };
  141. # Bind to `paperless-consumer` so that the server never runs
  142. # during migrations
  143. bindsTo = [ "paperless-consumer.service" ];
  144. after = [ "paperless-consumer.service" ];
  145. wantedBy = [ "multi-user.target" ];
  146. };
  147. users = optionalAttrs (cfg.user == defaultUser) {
  148. users.${defaultUser} = {
  149. group = defaultUser;
  150. uid = config.ids.uids.paperless;
  151. home = cfg.dataDir;
  152. };
  153. groups.${defaultUser} = {
  154. gid = config.ids.gids.paperless;
  155. };
  156. };
  157. };
  158. }