Merge #361424: refactor lib.packagesFromDirectoryRecursive (v2)
[NixPkgs.git] / nixos / modules / services / backup / tsm.nix
blob8dd27ccd2342490c70d756ea76e01da7cfa6a65a
1 { config, lib, ... }:
3 let
5   inherit (lib.attrsets) hasAttr;
6   inherit (lib.meta) getExe';
7   inherit (lib.modules) mkDefault mkIf;
8   inherit (lib.options) mkEnableOption mkOption;
9   inherit (lib.types) nonEmptyStr nullOr;
11   options.services.tsmBackup = {
12     enable = mkEnableOption ''
13       automatic backups with the
14       IBM Storage Protect (Tivoli Storage Manager, TSM) client.
15       This also enables
16       {option}`programs.tsmClient.enable`
17     '';
18     command = mkOption {
19       type = nonEmptyStr;
20       default = "backup";
21       example = "incr";
22       description = ''
23         The actual command passed to the
24         `dsmc` executable to start the backup.
25       '';
26     };
27     servername = mkOption {
28       type = nonEmptyStr;
29       example = "mainTsmServer";
30       description = ''
31         Create a systemd system service
32         `tsm-backup.service` that starts
33         a backup based on the given servername's stanza.
34         Note that this server's
35         {option}`passwdDir` will default to
36         {file}`/var/lib/tsm-backup/password`
37         (but may be overridden);
38         also, the service will use
39         {file}`/var/lib/tsm-backup` as
40         `HOME` when calling
41         `dsmc`.
42       '';
43     };
44     autoTime = mkOption {
45       type = nullOr nonEmptyStr;
46       default = null;
47       example = "12:00";
48       description = ''
49         The backup service will be invoked
50         automatically at the given date/time,
51         which must be in the format described in
52         {manpage}`systemd.time(5)`.
53         The default `null`
54         disables automatic backups.
55       '';
56     };
57   };
59   cfg = config.services.tsmBackup;
60   cfgPrg = config.programs.tsmClient;
62   assertions = [
63     {
64       assertion = hasAttr cfg.servername cfgPrg.servers;
65       message = "TSM service servername not found in list of servers";
66     }
67     {
68       assertion = cfgPrg.servers.${cfg.servername}.genPasswd;
69       message = "TSM service requires automatic password generation";
70     }
71   ];
77   inherit options;
79   config = mkIf cfg.enable {
80     inherit assertions;
81     programs.tsmClient.enable = true;
82     programs.tsmClient.servers.${cfg.servername}.passworddir = mkDefault "/var/lib/tsm-backup/password";
83     systemd.services.tsm-backup = {
84       description = "IBM Storage Protect (Tivoli Storage Manager) Backup";
85       # DSM_LOG needs a trailing slash to have it treated as a directory.
86       # `/var/log` would be littered with TSM log files otherwise.
87       environment.DSM_LOG = "/var/log/tsm-backup/";
88       # TSM needs a HOME dir to store certificates.
89       environment.HOME = "/var/lib/tsm-backup";
90       serviceConfig = {
91         # for exit status description see
92         # https://www.ibm.com/docs/en/storage-protect/8.1.24?topic=clients-client-return-codes
93         SuccessExitStatus = "4 8";
94         # The `-se` option must come after the command.
95         # The `-optfile` option suppresses a `dsm.opt`-not-found warning.
96         ExecStart = "${getExe' cfgPrg.wrappedPackage "dsmc"} ${cfg.command} -se='${cfg.servername}' -optfile=/dev/null";
97         LogsDirectory = "tsm-backup";
98         StateDirectory = "tsm-backup";
99         StateDirectoryMode = "0750";
100         # systemd sandboxing
101         LockPersonality = true;
102         NoNewPrivileges = true;
103         PrivateDevices = true;
104         #PrivateTmp = true;  # would break backup of {/var,}/tmp
105         #PrivateUsers = true;  # would block backup of /home/*
106         ProtectClock = true;
107         ProtectControlGroups = true;
108         ProtectHome = "read-only";
109         ProtectHostname = true;
110         ProtectKernelLogs = true;
111         ProtectKernelModules = true;
112         ProtectKernelTunables = true;
113         ProtectProc = "noaccess";
114         ProtectSystem = "strict";
115         RestrictNamespaces = true;
116         RestrictSUIDSGID = true;
117       };
118       startAt = mkIf (cfg.autoTime != null) cfg.autoTime;
119     };
120   };
122   meta.maintainers = [ lib.maintainers.yarny ];