diff options
Diffstat (limited to 'nixpkgs/nixos/modules/services/monitoring/smartd.nix')
-rw-r--r-- | nixpkgs/nixos/modules/services/monitoring/smartd.nix | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/monitoring/smartd.nix b/nixpkgs/nixos/modules/services/monitoring/smartd.nix new file mode 100644 index 000000000000..2c05eaad25ac --- /dev/null +++ b/nixpkgs/nixos/modules/services/monitoring/smartd.nix @@ -0,0 +1,252 @@ +{ config, lib, options, pkgs, ... }: + +with lib; + +let + + host = config.networking.fqdnOrHostName; + + cfg = config.services.smartd; + opt = options.services.smartd; + + nm = cfg.notifications.mail; + nw = cfg.notifications.wall; + nx = cfg.notifications.x11; + + smartdNotify = pkgs.writeScript "smartd-notify.sh" '' + #! ${pkgs.runtimeShell} + ${optionalString nm.enable '' + { + ${pkgs.coreutils}/bin/cat << EOF + From: smartd on ${host} <${nm.sender}> + To: ${nm.recipient} + Subject: $SMARTD_SUBJECT + + $SMARTD_FULLMESSAGE + EOF + + ${pkgs.smartmontools}/sbin/smartctl -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE" + } | ${nm.mailer} -i "${nm.recipient}" + ''} + ${optionalString nw.enable '' + { + ${pkgs.coreutils}/bin/cat << EOF + Problem detected with disk: $SMARTD_DEVICESTRING + Warning message from smartd is: + + $SMARTD_MESSAGE + EOF + } | ${pkgs.util-linux}/bin/wall 2>/dev/null + ''} + ${optionalString nx.enable '' + export DISPLAY=${nx.display} + { + ${pkgs.coreutils}/bin/cat << EOF + Problem detected with disk: $SMARTD_DEVICESTRING + Warning message from smartd is: + + $SMARTD_FULLMESSAGE + EOF + } | ${pkgs.xorg.xmessage}/bin/xmessage -file - 2>/dev/null & + ''} + ''; + + notifyOpts = optionalString (nm.enable || nw.enable || nx.enable) + ("-m <nomailer> -M exec ${smartdNotify} " + optionalString cfg.notifications.test "-M test "); + + smartdConf = pkgs.writeText "smartd.conf" '' + # Autogenerated smartd startup config file + DEFAULT ${notifyOpts}${cfg.defaults.monitored} + + ${concatMapStringsSep "\n" (d: "${d.device} ${d.options}") cfg.devices} + + ${optionalString cfg.autodetect + "DEVICESCAN ${notifyOpts}${cfg.defaults.autodetected}"} + ''; + + smartdDeviceOpts = { ... }: { + + options = { + + device = mkOption { + example = "/dev/sda"; + type = types.str; + description = "Location of the device."; + }; + + options = mkOption { + default = ""; + example = "-d sat"; + type = types.separatedString " "; + description = "Options that determine how smartd monitors the device."; + }; + + }; + + }; + +in + +{ + ###### interface + + options = { + + services.smartd = { + + enable = mkEnableOption "smartd daemon from `smartmontools` package"; + + autodetect = mkOption { + default = true; + type = types.bool; + description = '' + Whenever smartd should monitor all devices connected to the + machine at the time it's being started (the default). + + Set to false to monitor the devices listed in + {option}`services.smartd.devices` only. + ''; + }; + + extraOptions = mkOption { + default = []; + type = types.listOf types.str; + example = ["-A /var/log/smartd/" "--interval=3600"]; + description = '' + Extra command-line options passed to the `smartd` + daemon on startup. + + (See `man 8 smartd`.) + ''; + }; + + notifications = { + + mail = { + enable = mkOption { + default = config.services.mail.sendmailSetuidWrapper != null; + defaultText = literalExpression "config.services.mail.sendmailSetuidWrapper != null"; + type = types.bool; + description = "Whenever to send e-mail notifications."; + }; + + sender = mkOption { + default = "root"; + example = "example@domain.tld"; + type = types.str; + description = '' + Sender of the notification messages. + Acts as the value of `email` in the emails' `From: ...` field. + ''; + }; + + recipient = mkOption { + default = "root"; + type = types.str; + description = "Recipient of the notification messages."; + }; + + mailer = mkOption { + default = "/run/wrappers/bin/sendmail"; + type = types.path; + description = '' + Sendmail-compatible binary to be used to send the messages. + + You should probably enable + {option}`services.postfix` or some other MTA for + this to work. + ''; + }; + }; + + wall = { + enable = mkOption { + default = true; + type = types.bool; + description = "Whenever to send wall notifications to all users."; + }; + }; + + x11 = { + enable = mkOption { + default = config.services.xserver.enable; + defaultText = literalExpression "config.services.xserver.enable"; + type = types.bool; + description = "Whenever to send X11 xmessage notifications."; + }; + + display = mkOption { + default = ":${toString config.services.xserver.display}"; + defaultText = literalExpression ''":''${toString config.services.xserver.display}"''; + type = types.str; + description = "DISPLAY to send X11 notifications to."; + }; + }; + + test = mkOption { + default = false; + type = types.bool; + description = "Whenever to send a test notification on startup."; + }; + + }; + + defaults = { + monitored = mkOption { + default = "-a"; + type = types.separatedString " "; + example = "-a -o on -s (S/../.././02|L/../../7/04)"; + description = '' + Common default options for explicitly monitored (listed in + {option}`services.smartd.devices`) devices. + + The default value turns on monitoring of all the things (see + `man 5 smartd.conf`). + + The example also turns on SMART Automatic Offline Testing on + startup, and schedules short self-tests daily, and long + self-tests weekly. + ''; + }; + + autodetected = mkOption { + default = cfg.defaults.monitored; + defaultText = literalExpression "config.${opt.defaults.monitored}"; + type = types.separatedString " "; + description = '' + Like {option}`services.smartd.defaults.monitored`, but for the + autodetected devices. + ''; + }; + }; + + devices = mkOption { + default = []; + example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ]; + type = with types; listOf (submodule smartdDeviceOpts); + description = "List of devices to monitor."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + assertions = [ { + assertion = cfg.autodetect || cfg.devices != []; + message = "smartd can't run with both disabled autodetect and an empty list of devices to monitor."; + } ]; + + systemd.services.smartd = { + description = "S.M.A.R.T. Daemon"; + wantedBy = [ "multi-user.target" ]; + serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}"; + }; + + }; + +} |