diff --git a/flake.lock b/flake.lock index 2706421..e39e73e 100644 --- a/flake.lock +++ b/flake.lock @@ -1054,12 +1054,12 @@ "pre-commit-hooks": "pre-commit-hooks_2" }, "locked": { - "lastModified": 1705283066, - "narHash": "sha256-uYvo7hr28saTQuzZ+t0v2dPAxfcVLs4WirMuFl/ykAA=", - "owner": "oddlama", - "repo": "nixos-extra-modules", - "rev": "cab2f4b0408cc072a8f9405daa542298b11ea87b", - "type": "github" + "dirtyRev": "3057e049e731190def8e9c5bea5467b3edcdd93e-dirty", + "dirtyShortRev": "3057e04-dirty", + "lastModified": 1705280248, + "narHash": "sha256-c/BOXNxZ2Yf6FntFUxYROlxkxJ8kKfpjcwCxdwb9UAw=", + "type": "git", + "url": "file:///home/patrick/repos/nix/nixos-extra-modules" }, "original": { "owner": "oddlama", diff --git a/hosts/elisabeth/guests.nix b/hosts/elisabeth/guests.nix index bd83185..beb5434 100644 --- a/hosts/elisabeth/guests.nix +++ b/hosts/elisabeth/guests.nix @@ -11,6 +11,7 @@ nextclouddomain = "nc.${config.secrets.secrets.global.domains.web}"; giteadomain = "git.${config.secrets.secrets.global.domains.web}"; vaultwardendomain = "pw.${config.secrets.secrets.global.domains.web}"; + paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}"; ipOf = hostName: lib.net.cidr.host config.secrets.secrets.global.net.ips."${config.guests.${hostName}.nodeName}" config.secrets.secrets.global.net.privateSubnet; in { services.nginx = { @@ -35,6 +36,7 @@ in { client_max_body_size 1G ; ''; }; + upstreams.gitea = { servers."${ipOf "gitea"}:3000" = {}; @@ -54,6 +56,7 @@ in { client_max_body_size 1G ; ''; }; + upstreams.adguardhome = { servers."${ipOf "adguardhome"}:3000" = {}; @@ -74,6 +77,27 @@ in { deny all; ''; }; + upstreams.paperless = { + servers."${ipOf "paperless"}:3000" = {}; + + extraConfig = '' + zone paperless 64k ; + keepalive 5 ; + ''; + }; + virtualHosts.${paperlessdomain} = { + forceSSL = true; + useACMEHost = "web"; + locations."/" = { + proxyPass = "http://paperless"; + proxyWebsockets = true; + X-Frame-Options = "SAMEORIGIN"; + }; + extraConfig = '' + client_max_body_size 4G ; + ''; + }; + upstreams.nextcloud = { servers."${ipOf "nextcloud"}:80" = {}; @@ -96,6 +120,7 @@ in { enablePanzer ? false, enableRenaultFT ? false, enableBunker ? false, + enableSharedPaperless ? false, ... }: { autostart = true; @@ -119,6 +144,11 @@ in { pool = "panzer"; dataset = "bunker/guests/${guestName}"; }; + zfs."/paperless" = lib.mkIf enableSharedPaperless { + pool = "panzer"; + dataset = "bunker/shared/paperless"; + shared = true; + }; modules = [ ../../modules/config ../../modules/services/${guestName}.nix @@ -175,11 +205,16 @@ in { // mkContainer "nextcloud" { enablePanzer = true; } + // mkContainer "paperless" { + enableSharedPaperless = true; + } // mkContainer "gitea" { enablePanzer = true; } // mkContainer "samba" { enablePanzer = true; enableRenaultFT = true; + enableBunker = true; + enableSharedPaperless = true; }; } diff --git a/hosts/elisabeth/secrets/paperless/generated/paperless-admin-passwd.age b/hosts/elisabeth/secrets/paperless/generated/paperless-admin-passwd.age new file mode 100644 index 0000000..31960c0 --- /dev/null +++ b/hosts/elisabeth/secrets/paperless/generated/paperless-admin-passwd.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> X25519 Upc2gcbuYjkXNn8+FezCTEaWFjJQJHHVTIhrP0SUMkc +izickp9vEY4orPFyxda6xbdE4EK0vRSs+XmltAyKdKQ +-> piv-p256 XTQkUA A2buYDo2nM4vNAl9eZSejFa9d+ggM2v8OpyXxHw/GuU7 +dMOYZy/v1YiLnik+BgPn2Tb7X2DsmvSNRzVO9/gaOlk +-> piv-p256 ZFgiIw AuRRB6mIoiLiNdapfZxkHgvWFhq6Qkvnhu4CEy6H5OI9 +y13F4MuE/ZyMZYNfIIi6JIbsmHoR9UoDpW91GqZCgCI +-> piv-p256 5vmPtQ Az6XCDWVi7x6xKpbtNw7hZV831oHmaeP5qSejHFeEHRt +N809G8zW1IrVyU32mOuaC1TRAy6jkUJberP+JZzqa+A +-> piv-p256 ZFgiIw AjyP/+324TJKG5PqIiUTHv52OBNikuxJNndjx7AQVz6y +Zt2h5oLPD+M4PZFTL1NgDgtdByWa5lbrak+KJf+XIGA +-> *[Fh)-grease $,TX 2 5"~'m +rjXg4EA11HFFPHXjz9YcQOOrwlsfMTDy +--- QT0gtk2OI2ggsBiGPA38oUkT/8jWEt5yHoo8RCpN+P8 +MYy"!J'cW\\a$3zN#m2jQ{K TsK&vCV%{IP \ No newline at end of file diff --git a/hosts/elisabeth/secrets/paperless/host.pub b/hosts/elisabeth/secrets/paperless/host.pub new file mode 100644 index 0000000..1d0e17f --- /dev/null +++ b/hosts/elisabeth/secrets/paperless/host.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICZxPatFKKVFCC7JUsgvWb7/rb5IO+nttAm4v0Rzv++W diff --git a/modules/config/users.nix b/modules/config/users.nix index 772af05..c213937 100644 --- a/modules/config/users.nix +++ b/modules/config/users.nix @@ -23,6 +23,8 @@ radicale = uidGid 215; gitea = uidGid 215; vaultwarden = uidGid 215; + redis-paperless = uidGid 216; + paperless = uidGid 315; systemd-oom = uidGid 300; systemd-coredump = uidGid 301; patrick = uidGid 1000; diff --git a/modules/services/paperless.nix b/modules/services/paperless.nix new file mode 100644 index 0000000..100fd34 --- /dev/null +++ b/modules/services/paperless.nix @@ -0,0 +1,49 @@ +{ + config, + lib, + ... +}: let + paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}"; +in { + networking.firewall.allowedTCPPorts = [3000]; + age.secrets.paperless-admin-passwd = { + generator.script = "alnum"; + mode = "440"; + group = "paperless"; + }; + users.users.paperless.isSystemUser = true; + services.paperless = { + enable = true; + address = "0.0.0.0"; + port = 3000; + passwordFile = config.age.secrets.paperless-admin-passwd.path; + consumptionDir = "/paperless/consume"; + mediaDir = "/paperless/media"; + settings = { + PAPERLESS_URL = "https://${paperlessdomain}"; + PAPERLESS_ALLOWED_HOSTS = paperlessdomain; + PAPERLESS_CORS_ALLOWED_HOSTS = "https://${paperlessdomain}"; + PAPERLESS_TRUSTED_PROXIES = lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnet; + + # let nginx do all the compression + PAPERLESS_ENABLE_COMPRESSION = false; + PAPERLESS_CONSUMER_ENABLE_BARCODES = true; + PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE = true; + PAPERLESS_CONSUMER_BARCODE_SCANNER = "ZXING"; + PAPERLESS_CONSUMER_RECURSIVE = true; + PAPERLESS_FILENAME_FORMAT = "{owner_username}/{created_year}-{created_month}-{created_day}_{asn}_{title}"; + PAPERLESS_NUMBER_OF_SUGESSTED_DATES = 11; + PAPERLESS_OCR_LANGUAGE = "deu+eng"; + PAPERLESS_TASK_WORKERS = 4; + PAPERLESS_WEBSERVER_WORKERS = 4; + }; + }; + environment.persistence."/persist".directories = [ + { + directory = "/var/lib/paperless"; + user = "paperless"; + group = "paperless"; + mode = "0750"; + } + ]; +} diff --git a/modules/services/samba.nix b/modules/services/samba.nix index ec106dd..43ca8e4 100644 --- a/modules/services/samba.nix +++ b/modules/services/samba.nix @@ -91,17 +91,20 @@ user ? "smb", group ? "smb", hasBunker ? false, + hasPaperless ? false, persistRoot ? "/panzer", }: cfg: let config = { "#persistRoot" = persistRoot; + "#user" = user; + "#group" = group; "read only" = "no"; "guest ok" = "no"; "create mask" = "0740"; "directory mask" = "0750"; - "force user" = "${user}"; - "force group" = "${group}"; + "force user" = user; + "force group" = group; "valid users" = "${user} @${group}"; "force create mode" = "0660"; "force directory mode" = "0770"; @@ -123,6 +126,19 @@ "path" = "/media/smb/${name}-important"; "#persistRoot" = "/bunker"; }; + } + // lib.optionalAttrs hasPaperless + { + "${name}-paperless" = + config + // { + "path" = "/media/smb/${name}-paperless"; + "#paperless" = true; + "force user" = "paperless"; + "force group" = "paperless"; + # Empty to prevent imperamence setting a persistence folder + "#persistRoot" = ""; + }; }; in lib.mkMerge [ @@ -137,6 +153,7 @@ user = "patrick"; group = "patrick"; hasBunker = true; + hasPaperless = true; } {}) (mkShare { name = "helen-data"; @@ -176,16 +193,19 @@ users = lib.unique (lib.mapAttrsToList (_: val: val."force user") config.services.samba.shares); groups = lib.unique (users ++ (lib.mapAttrsToList (_: val: val."force group") config.services.samba.shares)); in { - users = lib.mkMerge (lib.flip map users (user: { - ${user} = { - isNormalUser = true; - home = "/var/empty"; - createHome = false; - useDefaultShell = false; - autoSubUidGidRange = false; - group = "${user}"; - }; - })); + users = lib.mkMerge ((lib.flip map users (user: { + ${user} = { + isNormalUser = true; + home = "/var/empty"; + createHome = false; + useDefaultShell = false; + autoSubUidGidRange = false; + group = "${user}"; + }; + })) + ++ [ + {paperless.isNormalUser = lib.mkForce false;} + ]); groups = lib.mkMerge ((lib.flip map groups (group: { ${group} = { }; @@ -193,14 +213,42 @@ ++ [{family.members = ["patrick" "david" "helen" "ggr"];}]); }; - environment.persistence = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: { - ${v."#persistRoot"}.directories = [ - { - directory = "${v.path}"; - user = "${v."force user"}"; - group = "${v."force group"}"; + fileSystems = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: + lib.optionalAttrs ((v ? "#paperless") && v."#paperless") { + "${v.path}/consume" = { + fsType = "none"; + options = ["bind"]; + device = "/paperless/consume/${v."#user"}"; + }; + "${v.path}/media" = { + fsType = "none "; + options = ["bind"]; + device = "/paperless/media/${v."#user"}"; + }; + })); + + systemd.tmpfiles.settings = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: + lib.optionalAttrs ((v ? "#paperless") && v."#paperless") { + "10-smb-paperless"."/paperless/consume/${v."#user"}".d = { + user = "paperless"; + group = "paperless"; mode = "0770"; - } - ]; - })); + }; + "10-smb-paperless"."/paperless/media/${v."#user"}".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + })); + environment.persistence = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: + lib.optionalAttrs ((v ? "#persistRoot") && (v."#persistRoot" != "")) { + ${v."#persistRoot"}.directories = [ + { + directory = "${v.path}"; + user = "${v."force user"}"; + group = "${v."force group"}"; + mode = "0770"; + } + ]; + })); } diff --git a/secrets/secrets.nix.age b/secrets/secrets.nix.age index ad1e141..bf36d74 100644 Binary files a/secrets/secrets.nix.age and b/secrets/secrets.nix.age differ