nixpkgs/nixos/modules/services/system/nvme-rs.nix
2025-09-27 08:44:52 +02:00

205 lines
6.1 KiB
Nix

{
config,
options,
lib,
pkgs,
...
}:
let
inherit (lib) types;
cfg = config.services.nvme-rs;
opt = options.services.nvme-rs;
settingsFormat = pkgs.formats.toml { };
in
{
options.services.nvme-rs = {
enable = lib.mkEnableOption "nvme-rs, a monitoring service";
package = lib.mkPackageOption pkgs "nvme-rs" { };
settings = lib.mkOption {
type = types.submodule {
freeformType = settingsFormat.type;
options = {
check_interval_secs = lib.mkOption {
type = types.int;
default = 3600;
description = "Check interval in seconds";
example = 86400;
};
thresholds = lib.mkOption {
type = types.submodule {
freeformType = settingsFormat.type;
options = {
temp_warning = lib.mkOption {
type = types.int;
default = 55;
description = "Temperature warning threshold (°C)";
};
temp_critical = lib.mkOption {
type = types.int;
default = 65;
description = "Temperature critical threshold (°C)";
};
wear_warning = lib.mkOption {
type = types.int;
default = 20;
description = "Wear warning threshold (%)";
};
wear_critical = lib.mkOption {
type = types.int;
default = 50;
description = "Wear critical threshold (%)";
};
spare_warning = lib.mkOption {
type = types.int;
default = 50;
description = "Available spare warning threshold (%)";
};
error_threshold = lib.mkOption {
type = types.int;
default = 100;
description = "Error count warning threshold";
};
};
};
default = { };
description = "Threshold configuration for NVMe monitoring";
};
email = lib.mkOption {
type = types.nullOr (
types.submodule {
freeformType = settingsFormat.type;
options = {
smtp_server = lib.mkOption {
type = types.str;
default = "smtp.gmail.com";
description = "SMTP server address";
example = "mail.example.com";
};
smtp_port = lib.mkOption {
type = types.port;
default = 587;
description = "SMTP server port";
};
smtp_username = lib.mkOption {
type = types.str;
description = "SMTP username";
example = "your-email@gmail.com";
};
smtp_password_file = lib.mkOption {
type = types.path;
description = "File containing SMTP password";
example = "/run/secrets/smtp-password";
};
from = lib.mkOption {
type = types.str;
description = "Sender email address";
example = "nvme-monitor@example.com";
};
to = lib.mkOption {
type = types.str;
description = "Recipient email address";
example = "admin@example.com";
};
use_tls = lib.mkOption {
type = types.bool;
default = true;
description = "Use TLS for SMTP connection";
};
};
}
);
default = null;
description = "Email notification configuration";
};
};
};
default = { };
description = ''
Configuration for nvme-rs in TOML format.
See the config.toml example for all available options.
'';
};
};
config = lib.mkIf cfg.enable {
services.nvme-rs.settings = opt.settings.default;
systemd.services.nvme-rs = {
description = "NVMe health monitoring service";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig =
let
settingsWithoutNull =
if cfg.settings.email == null then lib.removeAttrs cfg.settings [ "email" ] else cfg.settings;
configFile = settingsFormat.generate "nvme-rs.toml" settingsWithoutNull;
in
{
ExecStart = lib.escapeShellArgs [
"${lib.getExe cfg.package}"
"daemon"
"--config"
"${configFile}"
];
DynamicUser = true;
SupplementaryGroups = [ "disk" ];
CapabilityBoundingSet = [ "CAP_SYS_ADMIN" ];
AmbientCapabilities = [ "CAP_SYS_ADMIN" ];
LimitCORE = 0;
LimitNOFILE = 65535;
LockPersonality = true;
MemorySwapMax = 0;
MemoryZSwapMax = 0;
PrivateTmp = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
Restart = "on-failure";
RestartSec = "10s";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"@resources"
"~@privileged"
];
NoNewPrivileges = true;
UMask = "0077";
};
};
environment.systemPackages = [ cfg.package ];
};
}