grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / monitoring / scrutiny.nix
blobc0ead07066ec583a487ff77f5b21ed57eaee0ab4
1 { config, lib, pkgs, ... }:
2 let
3   inherit (lib) maintainers;
4   inherit (lib.meta) getExe;
5   inherit (lib.modules) mkIf mkMerge;
6   inherit (lib.options) literalExpression mkEnableOption mkOption mkPackageOption;
7   inherit (lib.types) bool enum nullOr port str submodule;
9   cfg = config.services.scrutiny;
10   # Define the settings format used for this program
11   settingsFormat = pkgs.formats.yaml { };
14   options = {
15     services.scrutiny = {
16       enable = mkEnableOption "Scrutiny, a web application for drive monitoring";
18       package = mkPackageOption pkgs "scrutiny" { };
20       openFirewall = mkEnableOption "opening the default ports in the firewall for Scrutiny";
22       influxdb.enable = mkOption {
23         type = bool;
24         default = true;
25         description = ''
26           Enables InfluxDB on the host system using the `services.influxdb2` NixOS module
27           with default options.
29           If you already have InfluxDB configured, or wish to connect to an external InfluxDB
30           instance, disable this option.
31         '';
32       };
34       settings = mkOption {
35         description = ''
36           Scrutiny settings to be rendered into the configuration file.
38           See https://github.com/AnalogJ/scrutiny/blob/master/example.scrutiny.yaml.
39         '';
40         default = { };
41         type = submodule {
42           freeformType = settingsFormat.type;
44           options.web.listen.port = mkOption {
45             type = port;
46             default = 8080;
47             description = "Port for web application to listen on.";
48           };
50           options.web.listen.host = mkOption {
51             type = str;
52             default = "0.0.0.0";
53             description = "Interface address for web application to bind to.";
54           };
56           options.web.listen.basepath = mkOption {
57             type = str;
58             default = "";
59             example = "/scrutiny";
60             description = ''
61               If Scrutiny will be behind a path prefixed reverse proxy, you can override this
62               value to serve Scrutiny on a subpath.
63             '';
64           };
66           options.log.level = mkOption {
67             type = enum [ "INFO" "DEBUG" ];
68             default = "INFO";
69             description = "Log level for Scrutiny.";
70           };
72           options.web.influxdb.scheme = mkOption {
73             type = str;
74             default = "http";
75             description = "URL scheme to use when connecting to InfluxDB.";
76           };
78           options.web.influxdb.host = mkOption {
79             type = str;
80             default = "0.0.0.0";
81             description = "IP or hostname of the InfluxDB instance.";
82           };
84           options.web.influxdb.port = mkOption {
85             type = port;
86             default = 8086;
87             description = "The port of the InfluxDB instance.";
88           };
90           options.web.influxdb.tls.insecure_skip_verify = mkEnableOption "skipping TLS verification when connecting to InfluxDB";
92           options.web.influxdb.token = mkOption {
93             type = nullOr str;
94             default = null;
95             description = "Authentication token for connecting to InfluxDB.";
96           };
98           options.web.influxdb.org = mkOption {
99             type = nullOr str;
100             default = null;
101             description = "InfluxDB organisation under which to store data.";
102           };
104           options.web.influxdb.bucket = mkOption {
105             type = nullOr str;
106             default = null;
107             description = "InfluxDB bucket in which to store data.";
108           };
109         };
110       };
112       collector = {
113         enable = mkEnableOption "the Scrutiny metrics collector" // {
114           default = cfg.enable;
115           defaultText = lib.literalExpression "config.services.scrutiny.enable";
116         };
118         package = mkPackageOption pkgs "scrutiny-collector" { };
120         schedule = mkOption {
121           type = str;
122           default = "*:0/15";
123           description = ''
124             How often to run the collector in systemd calendar format.
125           '';
126         };
128         settings = mkOption {
129           description = ''
130             Collector settings to be rendered into the collector configuration file.
132             See https://github.com/AnalogJ/scrutiny/blob/master/example.collector.yaml.
133           '';
134           default = { };
135           type = submodule {
136             freeformType = settingsFormat.type;
138             options.host.id = mkOption {
139               type = nullOr str;
140               default = null;
141               description = "Host ID for identifying/labelling groups of disks";
142             };
144             options.api.endpoint = mkOption {
145               type = str;
146               default = "http://${cfg.settings.web.listen.host}:${toString cfg.settings.web.listen.port}";
147               defaultText = literalExpression ''"http://''${config.services.scrutiny.settings.web.listen.host}:''${config.services.scrutiny.settings.web.listen.port}"'';
148               description = "Scrutiny app API endpoint for sending metrics to.";
149             };
151             options.log.level = mkOption {
152               type = enum [ "INFO" "DEBUG" ];
153               default = "INFO";
154               description = "Log level for Scrutiny collector.";
155             };
156           };
157         };
158       };
159     };
160   };
162   config = mkMerge [
163     (mkIf cfg.enable {
164       services.influxdb2.enable = cfg.influxdb.enable;
166       networking.firewall = mkIf cfg.openFirewall {
167         allowedTCPPorts = [ cfg.settings.web.listen.port ];
168       };
170       systemd.services.scrutiny = {
171         description = "Hard Drive S.M.A.R.T Monitoring, Historical Trends & Real World Failure Thresholds";
172         wantedBy = [ "multi-user.target" ];
173         after = [ "network.target" ] ++ lib.optional cfg.influxdb.enable "influxdb2.service";
174         wants = lib.optional cfg.influxdb.enable "influxdb2.service";
175         environment = {
176           SCRUTINY_VERSION = "1";
177           SCRUTINY_WEB_DATABASE_LOCATION = "/var/lib/scrutiny/scrutiny.db";
178           SCRUTINY_WEB_SRC_FRONTEND_PATH = "${cfg.package}/share/scrutiny";
179         };
180         serviceConfig = {
181           DynamicUser = true;
182           ExecStart = "${getExe cfg.package} start --config ${settingsFormat.generate "scrutiny.yaml" cfg.settings}";
183           Restart = "always";
184           StateDirectory = "scrutiny";
185           StateDirectoryMode = "0750";
186         };
187       };
188     })
189     (mkIf cfg.collector.enable {
190       services.smartd = {
191         enable = true;
192         extraOptions = [
193           "-A /var/log/smartd/"
194           "--interval=600"
195         ];
196       };
198       systemd = {
199         services.scrutiny-collector = {
200           description = "Scrutiny Collector Service";
201           after = lib.optional cfg.enable "scrutiny.service";
202           wants = lib.optional cfg.enable "scrutiny.service";
203           environment = {
204             COLLECTOR_VERSION = "1";
205             COLLECTOR_API_ENDPOINT = cfg.collector.settings.api.endpoint;
206           };
207           serviceConfig = {
208             Type = "oneshot";
209             ExecStart = "${getExe cfg.collector.package} run --config ${settingsFormat.generate "scrutiny-collector.yaml" cfg.collector.settings}";
210           };
211           startAt = cfg.collector.schedule;
212         };
214         timers.scrutiny-collector.timerConfig.Persistent = true;
215       };
216     })
217   ];
219   meta.maintainers = [ maintainers.jnsgruk ];