nixos/tests/networking: fix GRE test (#360349)
[NixPkgs.git] / nixos / modules / services / monitoring / smartd.nix
blob2cb5897f5d4c0310f4ed60c4c20e22585e367fb2
1 { config, lib, options, pkgs, ... }:
2 let
4   host = config.networking.fqdnOrHostName;
6   cfg = config.services.smartd;
7   opt = options.services.smartd;
9   nm = cfg.notifications.mail;
10   ns = cfg.notifications.systembus-notify;
11   nw = cfg.notifications.wall;
12   nx = cfg.notifications.x11;
14   smartdNotify = pkgs.writeScript "smartd-notify.sh" ''
15     #! ${pkgs.runtimeShell}
16     ${lib.optionalString nm.enable ''
17       {
18       ${pkgs.coreutils}/bin/cat << EOF
19       From: smartd on ${host} <${nm.sender}>
20       To: ${nm.recipient}
21       Subject: $SMARTD_SUBJECT
23       $SMARTD_FULLMESSAGE
24       EOF
26       ${pkgs.smartmontools}/sbin/smartctl -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE"
27       } | ${nm.mailer} -i "${nm.recipient}"
28     ''}
29     ${lib.optionalString ns.enable ''
30       ${pkgs.dbus}/bin/dbus-send --system \
31         / net.nuetzlich.SystemNotifications.Notify \
32         "string:Problem detected with disk: $SMARTD_DEVICESTRING" \
33         "string:Warning message from smartd is: $SMARTD_MESSAGE"
34     ''}
35     ${lib.optionalString nw.enable ''
36       {
37       ${pkgs.coreutils}/bin/cat << EOF
38       Problem detected with disk: $SMARTD_DEVICESTRING
39       Warning message from smartd is:
41       $SMARTD_MESSAGE
42       EOF
43       } | ${pkgs.util-linux}/bin/wall 2>/dev/null
44     ''}
45     ${lib.optionalString nx.enable ''
46       export DISPLAY=${nx.display}
47       {
48       ${pkgs.coreutils}/bin/cat << EOF
49       Problem detected with disk: $SMARTD_DEVICESTRING
50       Warning message from smartd is:
52       $SMARTD_FULLMESSAGE
53       EOF
54       } | ${pkgs.xorg.xmessage}/bin/xmessage -file - 2>/dev/null &
55     ''}
56   '';
58   notifyOpts = lib.optionalString (nm.enable || nw.enable || nx.enable)
59     ("-m <nomailer> -M exec ${smartdNotify} " + lib.optionalString cfg.notifications.test "-M test ");
61   smartdConf = pkgs.writeText "smartd.conf" ''
62     # Autogenerated smartd startup config file
63     DEFAULT ${notifyOpts}${cfg.defaults.monitored}
65     ${lib.concatMapStringsSep "\n" (d: "${d.device} ${d.options}") cfg.devices}
67     ${lib.optionalString cfg.autodetect
68        "DEVICESCAN ${notifyOpts}${cfg.defaults.autodetected}"}
69   '';
71   smartdDeviceOpts = { ... }: {
73     options = {
75       device = lib.mkOption {
76         example = "/dev/sda";
77         type = lib.types.str;
78         description = "Location of the device.";
79       };
81       options = lib.mkOption {
82         default = "";
83         example = "-d sat";
84         type = lib.types.separatedString " ";
85         description = "Options that determine how smartd monitors the device.";
86       };
88     };
90   };
95   ###### interface
97   options = {
99     services.smartd = {
101       enable = lib.mkEnableOption "smartd daemon from `smartmontools` package";
103       autodetect = lib.mkOption {
104         default = true;
105         type = lib.types.bool;
106         description = ''
107           Whenever smartd should monitor all devices connected to the
108           machine at the time it's being started (the default).
110           Set to false to monitor the devices listed in
111           {option}`services.smartd.devices` only.
112         '';
113       };
115       extraOptions = lib.mkOption {
116         default = [];
117         type = lib.types.listOf lib.types.str;
118         example = ["-A /var/log/smartd/" "--interval=3600"];
119         description = ''
120           Extra command-line options passed to the `smartd`
121           daemon on startup.
123           (See `man 8 smartd`.)
124         '';
125       };
127       notifications = {
129         mail = {
130           enable = lib.mkOption {
131             default = config.services.mail.sendmailSetuidWrapper != null;
132             defaultText = lib.literalExpression "config.services.mail.sendmailSetuidWrapper != null";
133             type = lib.types.bool;
134             description = "Whenever to send e-mail notifications.";
135           };
137           sender = lib.mkOption {
138             default = "root";
139             example = "example@domain.tld";
140             type = lib.types.str;
141             description = ''
142               Sender of the notification messages.
143               Acts as the value of `email` in the emails' `From: ...` field.
144             '';
145           };
147           recipient = lib.mkOption {
148             default = "root";
149             type = lib.types.str;
150             description = "Recipient of the notification messages.";
151           };
153           mailer = lib.mkOption {
154             default = "/run/wrappers/bin/sendmail";
155             type = lib.types.path;
156             description = ''
157               Sendmail-compatible binary to be used to send the messages.
159               You should probably enable
160               {option}`services.postfix` or some other MTA for
161               this to work.
162             '';
163           };
164         };
166         systembus-notify = {
167           enable = lib.mkOption {
168             default = false;
169             type = lib.types.bool;
170             description = ''
171               Whenever to send systembus-notify notifications.
173               WARNING: enabling this option (while convenient) should *not* be done on a
174               machine where you do not trust the other users as it allows any other
175               local user to DoS your session by spamming notifications.
177               To actually see the notifications in your GUI session, you need to have
178               `systembus-notify` running as your user, which this
179               option handles by enabling {option}`services.systembus-notify`.
180             '';
181           };
182         };
184         wall = {
185           enable = lib.mkOption {
186             default = true;
187             type = lib.types.bool;
188             description = "Whenever to send wall notifications to all users.";
189           };
190         };
192         x11 = {
193           enable = lib.mkOption {
194             default = config.services.xserver.enable;
195             defaultText = lib.literalExpression "config.services.xserver.enable";
196             type = lib.types.bool;
197             description = "Whenever to send X11 xmessage notifications.";
198           };
200           display = lib.mkOption {
201             default = ":${toString config.services.xserver.display}";
202             defaultText = lib.literalExpression ''":''${toString config.services.xserver.display}"'';
203             type = lib.types.str;
204             description = "DISPLAY to send X11 notifications to.";
205           };
206         };
208         test = lib.mkOption {
209           default = false;
210           type = lib.types.bool;
211           description = "Whenever to send a test notification on startup.";
212         };
214       };
216       defaults = {
217         monitored = lib.mkOption {
218           default = "-a";
219           type = lib.types.separatedString " ";
220           example = "-a -o on -s (S/../.././02|L/../../7/04)";
221           description = ''
222             Common default options for explicitly monitored (listed in
223             {option}`services.smartd.devices`) devices.
225             The default value turns on monitoring of all the things (see
226             `man 5 smartd.conf`).
228             The example also turns on SMART Automatic Offline Testing on
229             startup, and schedules short self-tests daily, and long
230             self-tests weekly.
231           '';
232         };
234         autodetected = lib.mkOption {
235           default = cfg.defaults.monitored;
236           defaultText = lib.literalExpression "config.${opt.defaults.monitored}";
237           type = lib.types.separatedString " ";
238           description = ''
239             Like {option}`services.smartd.defaults.monitored`, but for the
240             autodetected devices.
241           '';
242         };
243       };
245       devices = lib.mkOption {
246         default = [];
247         example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ];
248         type = with lib.types; listOf (submodule smartdDeviceOpts);
249         description = "List of devices to monitor.";
250       };
252     };
254   };
257   ###### implementation
259   config = lib.mkIf cfg.enable {
261     assertions = [ {
262       assertion = cfg.autodetect || cfg.devices != [];
263       message = "smartd can't run with both disabled autodetect and an empty list of devices to monitor.";
264     } ];
266     systemd.services.smartd = {
267       description = "S.M.A.R.T. Daemon";
268       wantedBy = [ "multi-user.target" ];
269       serviceConfig = {
270         Type = "notify";
271         ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}";
272       };
273     };
275     services.systembus-notify.enable = lib.mkDefault ns.enable;
277   };