at 25.11-pre 3.9 kB view raw
1{ config, lib, ... }: 2 3let 4 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; 10 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 }; 58 59 cfg = config.services.tsmBackup; 60 cfgPrg = config.programs.tsmClient; 61 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 ]; 72 73in 74 75{ 76 77 inherit options; 78 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.25?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 }; 121 122 meta.maintainers = [ lib.maintainers.yarny ]; 123 124}