at 18.09-beta 6.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 host = config.networking.hostName or "unknown" 8 + optionalString (config.networking.domain != null) ".${config.networking.domain}"; 9 10 cfg = config.services.smartd; 11 12 nm = cfg.notifications.mail; 13 nw = cfg.notifications.wall; 14 nx = cfg.notifications.x11; 15 16 smartdNotify = pkgs.writeScript "smartd-notify.sh" '' 17 #! ${pkgs.runtimeShell} 18 ${optionalString nm.enable '' 19 { 20 ${pkgs.coreutils}/bin/cat << EOF 21 From: smartd on ${host} <root> 22 To: undisclosed-recipients:; 23 Subject: SMART error on $SMARTD_DEVICESTRING: $SMARTD_FAILTYPE 24 25 $SMARTD_FULLMESSAGE 26 EOF 27 28 ${pkgs.smartmontools}/sbin/smartctl -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE" 29 } | ${nm.mailer} -i "${nm.recipient}" 30 ''} 31 ${optionalString nw.enable '' 32 { 33 ${pkgs.coreutils}/bin/cat << EOF 34 Problem detected with disk: $SMARTD_DEVICESTRING 35 Warning message from smartd is: 36 37 $SMARTD_MESSAGE 38 EOF 39 } | ${pkgs.utillinux}/bin/wall 2>/dev/null 40 ''} 41 ${optionalString nx.enable '' 42 export DISPLAY=${nx.display} 43 { 44 ${pkgs.coreutils}/bin/cat << EOF 45 Problem detected with disk: $SMARTD_DEVICESTRING 46 Warning message from smartd is: 47 48 $SMARTD_FULLMESSAGE 49 EOF 50 } | ${pkgs.xorg.xmessage}/bin/xmessage -file - 2>/dev/null & 51 ''} 52 ''; 53 54 notifyOpts = optionalString (nm.enable || nw.enable || nx.enable) 55 ("-m <nomailer> -M exec ${smartdNotify} " + optionalString cfg.notifications.test "-M test "); 56 57 smartdConf = pkgs.writeText "smartd.conf" '' 58 # Autogenerated smartd startup config file 59 DEFAULT ${notifyOpts}${cfg.defaults.monitored} 60 61 ${concatMapStringsSep "\n" (d: "${d.device} ${d.options}") cfg.devices} 62 63 ${optionalString cfg.autodetect 64 "DEVICESCAN ${notifyOpts}${cfg.defaults.autodetected}"} 65 ''; 66 67 smartdDeviceOpts = { ... }: { 68 69 options = { 70 71 device = mkOption { 72 example = "/dev/sda"; 73 type = types.str; 74 description = "Location of the device."; 75 }; 76 77 options = mkOption { 78 default = ""; 79 example = "-d sat"; 80 type = types.separatedString " "; 81 description = "Options that determine how smartd monitors the device."; 82 }; 83 84 }; 85 86 }; 87 88in 89 90{ 91 ###### interface 92 93 options = { 94 95 services.smartd = { 96 97 enable = mkEnableOption "smartd daemon from <literal>smartmontools</literal> package"; 98 99 autodetect = mkOption { 100 default = true; 101 type = types.bool; 102 description = '' 103 Whenever smartd should monitor all devices connected to the 104 machine at the time it's being started (the default). 105 106 Set to false to monitor the devices listed in 107 <option>services.smartd.devices</option> only. 108 ''; 109 }; 110 111 extraOptions = mkOption { 112 default = []; 113 type = types.listOf types.str; 114 example = ["-A /var/log/smartd/" "--interval=3600"]; 115 description = '' 116 Extra command-line options passed to the <literal>smartd</literal> 117 daemon on startup. 118 119 (See <literal>man 8 smartd</literal>.) 120 ''; 121 }; 122 123 notifications = { 124 125 mail = { 126 enable = mkOption { 127 default = config.services.mail.sendmailSetuidWrapper != null; 128 type = types.bool; 129 description = "Whenever to send e-mail notifications."; 130 }; 131 132 recipient = mkOption { 133 default = "root"; 134 type = types.str; 135 description = "Recipient of the notification messages."; 136 }; 137 138 mailer = mkOption { 139 default = "/run/wrappers/bin/sendmail"; 140 type = types.path; 141 description = '' 142 Sendmail-compatible binary to be used to send the messages. 143 144 You should probably enable 145 <option>services.postfix</option> or some other MTA for 146 this to work. 147 ''; 148 }; 149 }; 150 151 wall = { 152 enable = mkOption { 153 default = true; 154 type = types.bool; 155 description = "Whenever to send wall notifications to all users."; 156 }; 157 }; 158 159 x11 = { 160 enable = mkOption { 161 default = config.services.xserver.enable; 162 type = types.bool; 163 description = "Whenever to send X11 xmessage notifications."; 164 }; 165 166 display = mkOption { 167 default = ":${toString config.services.xserver.display}"; 168 type = types.str; 169 description = "DISPLAY to send X11 notifications to."; 170 }; 171 }; 172 173 test = mkOption { 174 default = false; 175 type = types.bool; 176 description = "Whenever to send a test notification on startup."; 177 }; 178 179 }; 180 181 defaults = { 182 monitored = mkOption { 183 default = "-a"; 184 type = types.separatedString " "; 185 example = "-a -o on -s (S/../.././02|L/../../7/04)"; 186 description = '' 187 Common default options for explicitly monitored (listed in 188 <option>services.smartd.devices</option>) devices. 189 190 The default value turns on monitoring of all the things (see 191 <literal>man 5 smartd.conf</literal>). 192 193 The example also turns on SMART Automatic Offline Testing on 194 startup, and schedules short self-tests daily, and long 195 self-tests weekly. 196 ''; 197 }; 198 199 autodetected = mkOption { 200 default = cfg.defaults.monitored; 201 type = types.separatedString " "; 202 description = '' 203 Like <option>services.smartd.defaults.monitored</option>, but for the 204 autodetected devices. 205 ''; 206 }; 207 }; 208 209 devices = mkOption { 210 default = []; 211 example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ]; 212 type = with types; listOf (submodule smartdDeviceOpts); 213 description = "List of devices to monitor."; 214 }; 215 216 }; 217 218 }; 219 220 221 ###### implementation 222 223 config = mkIf cfg.enable { 224 225 assertions = [ { 226 assertion = cfg.autodetect || cfg.devices != []; 227 message = "smartd can't run with both disabled autodetect and an empty list of devices to monitor."; 228 } ]; 229 230 systemd.services.smartd = { 231 description = "S.M.A.R.T. Daemon"; 232 233 wantedBy = [ "multi-user.target" ]; 234 235 path = [ pkgs.nettools ]; # for hostname and dnsdomanname calls in smartd 236 237 serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}"; 238 }; 239 240 }; 241 242}