Files
Yarny0 2ad8bf20ed tsm-client: 8.1.27.1 -> 8.2.1.0
Release notes ("What's new"):
https://www.ibm.com/docs/en/storage-protect/8.2.1?topic=whats-new#r_wn_tsmserver__title__3

The package now needs `brotli` and `libnghttp2`.

Unfortunatelly, the vm test's OCR no longer recognizes
the version number in the information dialog box
(it sees "8.21.0" instead of "8.2.1.0").
I don't think relaxing that test makes any sense,
as OCR might fail in a million different ways.
So I just remove the version number check from the test.
2026-03-27 19:31:06 +01:00

125 lines
3.9 KiB
Nix

{ config, lib, ... }:
let
inherit (lib.attrsets) hasAttr;
inherit (lib.meta) getExe';
inherit (lib.modules) mkDefault mkIf;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) nonEmptyStr nullOr;
options.services.tsmBackup = {
enable = mkEnableOption ''
automatic backups with the
IBM Storage Protect (Tivoli Storage Manager, TSM) client.
This also enables
{option}`programs.tsmClient.enable`
'';
command = mkOption {
type = nonEmptyStr;
default = "backup";
example = "incr";
description = ''
The actual command passed to the
`dsmc` executable to start the backup.
'';
};
servername = mkOption {
type = nonEmptyStr;
example = "mainTsmServer";
description = ''
Create a systemd system service
`tsm-backup.service` that starts
a backup based on the given servername's stanza.
Note that this server's
{option}`passwdDir` will default to
{file}`/var/lib/tsm-backup/password`
(but may be overridden);
also, the service will use
{file}`/var/lib/tsm-backup` as
`HOME` when calling
`dsmc`.
'';
};
autoTime = mkOption {
type = nullOr nonEmptyStr;
default = null;
example = "12:00";
description = ''
The backup service will be invoked
automatically at the given date/time,
which must be in the format described in
{manpage}`systemd.time(5)`.
The default `null`
disables automatic backups.
'';
};
};
cfg = config.services.tsmBackup;
cfgPrg = config.programs.tsmClient;
assertions = [
{
assertion = hasAttr cfg.servername cfgPrg.servers;
message = "TSM service servername not found in list of servers";
}
{
assertion = cfgPrg.servers.${cfg.servername}.genPasswd;
message = "TSM service requires automatic password generation";
}
];
in
{
inherit options;
config = mkIf cfg.enable {
inherit assertions;
programs.tsmClient.enable = true;
programs.tsmClient.servers.${cfg.servername}.passworddir = mkDefault "/var/lib/tsm-backup/password";
systemd.services.tsm-backup = {
description = "IBM Storage Protect (Tivoli Storage Manager) Backup";
# DSM_LOG needs a trailing slash to have it treated as a directory.
# `/var/log` would be littered with TSM log files otherwise.
environment.DSM_LOG = "/var/log/tsm-backup/";
# TSM needs a HOME dir to store certificates.
environment.HOME = "/var/lib/tsm-backup";
serviceConfig = {
# for exit status description see
# https://www.ibm.com/docs/en/storage-protect/8.2.1?topic=clients-client-return-codes
SuccessExitStatus = "4 8";
# The `-se` option must come after the command.
# The `-optfile` option suppresses a `dsm.opt`-not-found warning.
ExecStart = "${getExe' cfgPrg.wrappedPackage "dsmc"} ${cfg.command} -se='${cfg.servername}' -optfile=/dev/null";
LogsDirectory = "tsm-backup";
StateDirectory = "tsm-backup";
StateDirectoryMode = "0750";
# systemd sandboxing
LockPersonality = true;
NoNewPrivileges = true;
PrivateDevices = true;
#PrivateTmp = true; # would break backup of {/var,}/tmp
#PrivateUsers = true; # would block backup of /home/*
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = "read-only";
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "noaccess";
ProtectSystem = "strict";
RestrictNamespaces = true;
RestrictSUIDSGID = true;
};
startAt = mkIf (cfg.autoTime != null) cfg.autoTime;
};
};
meta.maintainers = [ lib.maintainers.yarny ];
}