nixos-config/services/paperless.nix
2024-05-20 15:50:41 +02:00

106 lines
3.2 KiB
Nix

{ config, lib, my, pkgs, secrets, ... }:
let
paperlessEnv = config.services.paperless.settings;
redisSocketPath = config.services.redis.servers.paperless.unixSocket;
vhost = "paperless.${my.domain}";
in {
services.paperless = {
enable = true;
address = "[::1]";
settings = {
PAPERLESS_OCR_LANGUAGE = "deu+eng";
# also allows importing (most) digitally signed PDFs, at least any with
# text already embedded, e.g. Austrian e-gov documents
PAPERLESS_OCR_SKIP_ARCHIVE_FILE = "with_text";
PAPERLESS_REDIS = "unix://${redisSocketPath}";
PAPERLESS_DBHOST = "/run/postgresql";
PAPERLESS_DBNAME = "paperless";
PAPERLESS_DBUSER = "paperless";
PAPERLESS_SSLMODE = "disable";
PAPERLESS_URL = "https://${vhost}";
PAPERLESS_USE_X_FORWARD_HOST = true;
PAPERLESS_USE_X_FORWARD_PORT = true;
};
};
services.redis.vmOverCommit = true;
services.redis.servers.paperless = {
enable = true;
databases = 16;
maxclients = 128;
user = "paperless";
port = 0; # disable TCP
settings = {
maxmemory = "128MB";
maxmemory-policy = "volatile-ttl";
};
};
services.postgresql = {
ensureDatabases = [ paperlessEnv.PAPERLESS_DBNAME ];
ensureUsers = [{
name = paperlessEnv.PAPERLESS_DBUSER;
ensureDBOwnership =
assert paperlessEnv.PAPERLESS_DBNAME == paperlessEnv.PAPERLESS_DBNAME;
true;
ensureClauses.login = true;
}];
};
systemd.services = lib.mkMerge [
# Binds the redis socket into services that need it
(let services = [ "scheduler" "task-queue" "web" ];
in builtins.listToAttrs (map (name: {
name = "paperless-${name}";
value = {
serviceConfig.BindReadOnlyPaths = [ redisSocketPath ];
requires = [ "redis-paperless.service" ];
after = [ "redis-paperless.service" ];
};
}) services))
{
# Ensure that redis is available before it starts
paperless-download-nltk-data = {
requires = [ "redis-paperless.service" ];
after = [ "redis-paperless.service" "network-online.target" ];
wants = [ "network-online.target" ];
preStart = "${pkgs.toybox}/bin/sleep 10";
};
}
];
services.nginx.virtualHosts.${vhost} = {
forceSSL = true;
useACMEHost = my.domain;
kTLS = true;
locations."/" = {
proxyPass = "http://[::1]:${toString config.services.paperless.port}";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size 512M;
'';
};
};
users.users.paperless.extraGroups = [ "restic-backup" ];
services.restic.backups.paperless-media = {
environmentFile = secrets."restic/rest-env".path;
initialize = true;
repository =
"${my.homelab.services.restic.repositoryBase}/${config.networking.hostName}";
passwordFile = secrets."restic/repo-password".path;
user = "paperless";
paths = [
"/var/lib/paperless/media/documents"
"/var/lib/paperless/classification_model.pickle"
];
timerConfig.OnCalendar = "*-*-* 4:00:00"; # daily at 04:00
backupCleanupCommand = my.mkResticBackupNotificationCmd {
name = "paperless-media";
inherit pkgs secrets;
};
};
}