···
7
+
host = config.networking.hostName or "unknown"
8
+
+ optionalString (config.networking.domain != null) ".${config.networking.domain}";
cfg = config.services.smartd;
12
+
nm = cfg.notifications.mail;
13
+
nw = cfg.notifications.wall;
14
+
nx = cfg.notifications.x11;
16
+
smartdNotify = pkgs.writeScript "smartd-notify.sh" ''
17
+
#! ${pkgs.stdenv.shell}
18
+
${optionalString nm.enable ''
21
+
From: smartd on ${host} <root>
22
+
To: undisclosed-recipients:;
23
+
Subject: SMART error on $SMARTD_DEVICESTRING: $SMARTD_FAILTYPE
28
+
${pkgs.smartmontools}/sbin/smartctl -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE"
29
+
} | ${nm.mailer} -i "${nm.recipient}"
31
+
${optionalString nw.enable ''
34
+
Problem detected with disk: $SMARTD_DEVICESTRING
35
+
Warning message from smartd is:
39
+
} | ${pkgs.utillinux}/bin/wall 2>/dev/null
41
+
${optionalString nx.enable ''
42
+
export DISPLAY=${nx.display}
45
+
Problem detected with disk: $SMARTD_DEVICESTRING
46
+
Warning message from smartd is:
50
+
} | ${pkgs.xorg.xmessage}/bin/xmessage -file - 2>/dev/null &
54
+
notifyOpts = optionalString (nm.enable || nw.enable || nx.enable)
55
+
("-m <nomailer> -M exec ${smartdNotify} " + optionalString cfg.notifications.test "-M test ");
57
+
smartdConf = pkgs.writeText "smartd.conf" ''
58
+
# Autogenerated smartd startup config file
59
+
DEFAULT ${notifyOpts}${cfg.defaults.monitored}
61
+
${concatMapStringsSep "\n" (d: "${d.device} ${d.options}") cfg.devices}
63
+
${optionalString cfg.autodetect
64
+
"DEVICESCAN ${notifyOpts}${cfg.defaults.autodetected}"}
smartdOpts = { name, ... }: {
···
type = types.separatedString " ";
description = "Options that determine how smartd monitors the device.";
29
-
smartdMail = pkgs.writeScript "smartdmail.sh" ''
30
-
#! ${pkgs.stdenv.shell}
31
-
TMPNAM=/tmp/smartd-message.$$.tmp
32
-
if test -n "$SMARTD_ADDRESS"; then
33
-
echo >"$TMPNAM" "From: smartd <root>"
34
-
echo >>"$TMPNAM" 'To: undisclosed-recipients:;'
35
-
echo >>"$TMPNAM" "Subject: $SMARTD_SUBJECT"
37
-
echo >>"$TMPNAM" "Failure on $SMARTD_DEVICESTRING: $SMARTD_FAILTYPE"
40
-
${pkgs.smartmontools}/sbin/smartctl >>"$TMPNAM" -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE"
41
-
/var/setuid-wrappers/sendmail <"$TMPNAM" -f "$SENDER" -i "$SMARTD_ADDRESS"
45
-
smartdConf = pkgs.writeText "smartd.conf" (concatMapStrings (device:
47
-
${device.device} -a -m root -M exec ${smartdMail} ${device.options} ${cfg.deviceOpts}
51
-
smartdFlags = if (cfg.devices == []) then "" else "--configfile=${smartdConf}";
···
97
+
enable = mkEnableOption "smartd daemon from <literal>smartmontools</literal> package";
99
+
autodetect = mkOption {
67
-
Run smartd from the smartmontools package. Note that e-mail
68
-
notifications will not be enabled unless you configure the list of
69
-
devices with <varname>services.smartd.devices</varname> as well.
103
+
Whenever smartd should monitor all devices connected to the
104
+
machine at the time it's being started (the default).
106
+
Set to false to monitor the devices listed in
107
+
<option>services.smartd.devices</option> only.
73
-
deviceOpts = mkOption {
75
-
type = types.string;
76
-
example = "-o on -s (S/../.././02|L/../../7/04)";
78
-
Additional options for each device that is monitored. The example
79
-
turns on SMART Automatic Offline Testing on startup, and schedules short
80
-
self-tests daily, and long self-tests weekly.
114
+
enable = mkOption {
115
+
default = config.services.mail.sendmailSetuidWrapper != null;
117
+
description = "Whenever to send e-mail notifications.";
120
+
recipient = mkOption {
122
+
type = types.string;
123
+
description = "Recipient of the notification messages.";
126
+
mailer = mkOption {
127
+
default = "/var/setuid-wrappers/sendmail";
130
+
Sendmail-compatible binary to be used to send the messages.
132
+
You should probably enable
133
+
<option>services.postfix</option> or some other MTA for
140
+
enable = mkOption {
143
+
description = "Whenever to send wall notifications to all users.";
148
+
enable = mkOption {
149
+
default = config.services.xserver.enable;
151
+
description = "Whenever to send X11 xmessage notifications.";
154
+
display = mkOption {
155
+
default = ":${toString config.services.xserver.display}";
156
+
type = types.string;
157
+
description = "DISPLAY to send X11 notifications to.";
164
+
description = "Whenever to send a test notification on startup.";
170
+
monitored = mkOption {
172
+
type = types.separatedString " ";
173
+
example = "-a -o on -s (S/../.././02|L/../../7/04)";
175
+
Common default options for explicitly monitored (listed in
176
+
<option>services.smartd.devices</option>) devices.
178
+
The default value turns on monitoring of all the things (see
179
+
<literal>man 5 smartd.conf</literal>).
181
+
The example also turns on SMART Automatic Offline Testing on
182
+
startup, and schedules short self-tests daily, and long
187
+
autodetected = mkOption {
188
+
default = cfg.defaults.monitored;
189
+
type = types.separatedString " ";
191
+
Like <option>services.smartd.defaults.monitored</option>, but for the
192
+
autodetected devices.
···
example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ];
type = types.listOf types.optionSet;
options = [ smartdOpts ];
90
-
List of devices to monitor. By default -- if this list is empty --,
91
-
smartd will monitor all devices connected to the machine at the time
92
-
it's being run. Configuring this option has the added benefit of
93
-
enabling e-mail notifications to "root" every time smartd detects an
202
+
description = "List of devices to monitor.";
···
config = mkIf cfg.enable {
215
+
assertion = cfg.autodetect || cfg.devices != [];
216
+
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" ];
111
-
serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd --no-fork ${smartdFlags}";
224
+
path = [ pkgs.nettools ]; # for hostname and dnsdomanname calls in smartd
226
+
serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd --no-fork --configfile=${smartdConf}";