diff --git a/hosts/stratus/containers/paperless/backup.nix b/hosts/stratus/containers/paperless/backup.nix new file mode 100644 index 0000000..52c2791 --- /dev/null +++ b/hosts/stratus/containers/paperless/backup.nix @@ -0,0 +1,65 @@ +{ + config, + pkgs, + lib, + dataDir, + ... +}: +{ + sops.secrets = { + "restic/environment" = { + owner = config.users.users.paperless.name; + inherit (config.users.users.paperless) group; + }; + "restic/password" = { + owner = config.users.users.paperless.name; + inherit (config.users.users.paperless) group; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir}/backup 700 paperless paperless -" + "d /var/cache/restic-backups-paperless 700 paperless paperless -" + ]; + + services.restic.backups.paperless = { + inherit (config.services.paperless) user; + initialize = true; + + repository = "s3:https://s3.eu-central-003.backblazeb2.com/stork-atlas/paperless"; + environmentFile = config.sops.secrets."restic/environment".path; + passwordFile = config.sops.secrets."restic/password".path; + + pruneOpts = [ + "--keep-daily 7" + "--keep-weekly 5" + "--keep-monthly 6" + "--keep-yearly 1" + ]; + + backupPrepareCommand = '' + ${dataDir}/paperless-manage document_exporter ${dataDir}/backup ${ + lib.concatStringsSep " " [ + "--compare-checksums" + "--delete" + "--split-manifest" + "--use-filename-format" + "--no-progress-bar" + ] + } + ''; + + paths = [ "${dataDir}/backup" ]; + }; + + users.users.paperless.extraGroups = [ "redis-paperless" ]; + environment.systemPackages = [ + (pkgs.writeShellApplication { + name = "restore-paperless"; + text = '' + sudo -u paperless restic-paperless restore --target / latest + sudo -u paperless ${dataDir}/paperless-manage document_importer ${dataDir}/backup + ''; + }) + ]; +} diff --git a/hosts/stratus/containers/paperless/default.nix b/hosts/stratus/containers/paperless/default.nix index 1a0cb7e..9206f73 100644 --- a/hosts/stratus/containers/paperless/default.nix +++ b/hosts/stratus/containers/paperless/default.nix @@ -6,6 +6,8 @@ ... }: { + imports = [ ./backup.nix ]; + sops.secrets."paperless-admin-password" = { }; services.paperless = { diff --git a/hosts/stratus/containers/paperless/secrets.yaml b/hosts/stratus/containers/paperless/secrets.yaml index c807cde..6651166 100644 --- a/hosts/stratus/containers/paperless/secrets.yaml +++ b/hosts/stratus/containers/paperless/secrets.yaml @@ -1,31 +1,34 @@ tailscale-auth-key: ENC[AES256_GCM,data:2vJoEaMZE1s2cVL20A7JCaZ525YkSXqCasKcCLwbYX+W8BVczEDThPqXm2PyKzo6zcdkZkbwONWIeLKEhyE=,iv:Z/B0tUMn+ACLT5is+TRjLOT16FpdWhTuDC1llvNZ7Ms=,tag:pwzlgMkuNYEhmZ/uiRJy4Q==,type:str] paperless-admin-password: ENC[AES256_GCM,data:7xjn0fXEFZCYDvzjP7P5R5reZR8=,iv:jMIJNbqEo7IcHDYwvTmQnArYdt2PR9tp8coOXCZHkQw=,tag:kCejUFStTuosRblkbQMdew==,type:str] +restic: + environment: ENC[AES256_GCM,data:JRwMFhbVLg4hkmJsNw+yNdCBX3Cud5ADbGL+nkRFUjpMkF1c3JubWnNI4lG/ehfJ0GJmHveOyMD304XEykPWuK89KVNNmqTuaa2hGUIykQPyqAqvkChOsOZAfGA/gHrC8tY=,iv:xsXanfAtI8ppOxwtsu89+3KWwNXtXPyT1k+Toe6f6Vw=,tag:hUO7jaTgzX+z4eiLK9CQ7g==,type:str] + password: ENC[AES256_GCM,data:txtSW2r1HTFeZXEmkkMBYhPkdms=,iv:kTI52zpI7vUU6IxO/qwzoAtdNZnHrhU69WovA1dBYi0=,tag:6XF1BUOA2Brao/qR3DNe0g==,type:str] sops: - kms: [] - gcp_kms: [] - azure_kv: [] - hc_vault: [] - age: - - recipient: age1mpq8m4p7dnxh5ze3fh7etd2k6sp85zdnmp9te3e9chcw4pw07pcq960zh5 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWTmZLR2JOM1p2S2lxYkts - WTE2OFlRUXJ0a01EOUd3Mythc3R1d3llTTNrCkJQWVY1bGlFbThaL0plTWhwYUJK - WDlQNjFzZGhIS3ZlaHZiYytQdFo5WWMKLS0tIGZ3VDRTQlFHT2IwVkFIb0lwOXhT - dm9QRndWZXE0L0drS3JzMGF0c2x1S1kKXuxMaVAcbRwR4/QZnIUdb3wyRujYAy2I - 8/FYL5r9PuNwhEv1Ene+dj8nkx1G+stTZmgepOS9Z0AyIvfDW6FS8g== - -----END AGE ENCRYPTED FILE----- - - recipient: age1y82j460w5fh0fpquatqar0zqet0vzzfzjnegrp686na3gejapdtsc37vuh - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNMVVzZUl5WVc3VVZudmVj - UkVDd2pYUU50MDBHRnZ4Sis5K28wV1RwNlQ4CmhONVd3Wkh5ZHlYSDYzeHlLMGdF - VUxiS2JWS2lwQVY2OHYwSk1UdGNSeUkKLS0tIGRSZVJ2U1J6azQveHJkRmViVnNs - cmFJeFpHdnRzMFA2a1NML1A1RFB6clEK+FH8x1dccz8TnUuEFc0EkTSzG6Ody0IF - tCNrHN2h3AzqYxKFYucquMmnE9WGJuzShijIXAv1W7JE2JZw9XnS4w== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-09-02T11:38:42Z" - mac: ENC[AES256_GCM,data:IkUwDpVTUboAHQzFMaHhcGkNtW1eGUNrGDDEq9Zegwrwu6Xx5yFuxlmFMWIM7oX3voWjCx4A1u4sxfT4JHauhnJER7rXeF5qYuGSiIj8o2rMZYm7C6zkWumJ7kvt5nBML5+Jkd8n9fhbh9wSND1IbzsWwuURugeNLhYvUaCJA+Y=,iv:8aoHhE/rZYEf6vtvQvuuG1CDnCniarxxIC0ysH6Hemo=,tag:93B38zvR3Qx8rawO9CuJ4w==,type:str] - pgp: [] - unencrypted_suffix: _unencrypted - version: 3.9.0 + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1mpq8m4p7dnxh5ze3fh7etd2k6sp85zdnmp9te3e9chcw4pw07pcq960zh5 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWTmZLR2JOM1p2S2lxYkts + WTE2OFlRUXJ0a01EOUd3Mythc3R1d3llTTNrCkJQWVY1bGlFbThaL0plTWhwYUJK + WDlQNjFzZGhIS3ZlaHZiYytQdFo5WWMKLS0tIGZ3VDRTQlFHT2IwVkFIb0lwOXhT + dm9QRndWZXE0L0drS3JzMGF0c2x1S1kKXuxMaVAcbRwR4/QZnIUdb3wyRujYAy2I + 8/FYL5r9PuNwhEv1Ene+dj8nkx1G+stTZmgepOS9Z0AyIvfDW6FS8g== + -----END AGE ENCRYPTED FILE----- + - recipient: age1y82j460w5fh0fpquatqar0zqet0vzzfzjnegrp686na3gejapdtsc37vuh + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNMVVzZUl5WVc3VVZudmVj + UkVDd2pYUU50MDBHRnZ4Sis5K28wV1RwNlQ4CmhONVd3Wkh5ZHlYSDYzeHlLMGdF + VUxiS2JWS2lwQVY2OHYwSk1UdGNSeUkKLS0tIGRSZVJ2U1J6azQveHJkRmViVnNs + cmFJeFpHdnRzMFA2a1NML1A1RFB6clEK+FH8x1dccz8TnUuEFc0EkTSzG6Ody0IF + tCNrHN2h3AzqYxKFYucquMmnE9WGJuzShijIXAv1W7JE2JZw9XnS4w== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-09-02T11:41:12Z" + mac: ENC[AES256_GCM,data:BPT+RVvdUxbNmhKUEqagk3XBaxG9+o40u29oyKPWPC8L62j7FgKjihoMKEKtiGTuswQdwNiHrz2QAAcQ90yXE0WVQC2yho7QvoejTTVkkii2fh9+AGWFffQXQ1GNXqPVsTF5d8vkLkEMipZqatObC4yFQgffIvQfAMHPPHCxdsc=,iv:e8ENMa8cZ+q5JJD1JqhdjQazxI8jzwQqZEdX/M0+zMY=,tag:mhFfY2rP/XKFazjFuBVVmQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.0