at 24.11-pre 7.2 kB view raw
1{ config, lib, pkgs, ... }: 2let 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; 8 9 cfg = config.services.scrutiny; 10 # Define the settings format used for this program 11 settingsFormat = pkgs.formats.yaml { }; 12in 13{ 14 options = { 15 services.scrutiny = { 16 enable = mkEnableOption "Scrutiny, a web application for drive monitoring"; 17 18 package = mkPackageOption pkgs "scrutiny" { }; 19 20 openFirewall = mkEnableOption "opening the default ports in the firewall for Scrutiny"; 21 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. 28 29 If you already have InfluxDB configured, or wish to connect to an external InfluxDB 30 instance, disable this option. 31 ''; 32 }; 33 34 settings = mkOption { 35 description = '' 36 Scrutiny settings to be rendered into the configuration file. 37 38 See https://github.com/AnalogJ/scrutiny/blob/master/example.scrutiny.yaml. 39 ''; 40 default = { }; 41 type = submodule { 42 freeformType = settingsFormat.type; 43 44 options.web.listen.port = mkOption { 45 type = port; 46 default = 8080; 47 description = "Port for web application to listen on."; 48 }; 49 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 }; 55 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 }; 65 66 options.log.level = mkOption { 67 type = enum [ "INFO" "DEBUG" ]; 68 default = "INFO"; 69 description = "Log level for Scrutiny."; 70 }; 71 72 options.web.influxdb.scheme = mkOption { 73 type = str; 74 default = "http"; 75 description = "URL scheme to use when connecting to InfluxDB."; 76 }; 77 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 }; 83 84 options.web.influxdb.port = mkOption { 85 type = port; 86 default = 8086; 87 description = "The port of the InfluxDB instance."; 88 }; 89 90 options.web.influxdb.tls.insecure_skip_verify = mkEnableOption "skipping TLS verification when connecting to InfluxDB"; 91 92 options.web.influxdb.token = mkOption { 93 type = nullOr str; 94 default = null; 95 description = "Authentication token for connecting to InfluxDB."; 96 }; 97 98 options.web.influxdb.org = mkOption { 99 type = nullOr str; 100 default = null; 101 description = "InfluxDB organisation under which to store data."; 102 }; 103 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 }; 111 112 collector = { 113 enable = mkEnableOption "the Scrutiny metrics collector"; 114 115 package = mkPackageOption pkgs "scrutiny-collector" { }; 116 117 schedule = mkOption { 118 type = str; 119 default = "*:0/15"; 120 description = '' 121 How often to run the collector in systemd calendar format. 122 ''; 123 }; 124 125 settings = mkOption { 126 description = '' 127 Collector settings to be rendered into the collector configuration file. 128 129 See https://github.com/AnalogJ/scrutiny/blob/master/example.collector.yaml. 130 ''; 131 default = { }; 132 type = submodule { 133 freeformType = settingsFormat.type; 134 135 options.host.id = mkOption { 136 type = nullOr str; 137 default = null; 138 description = "Host ID for identifying/labelling groups of disks"; 139 }; 140 141 options.api.endpoint = mkOption { 142 type = str; 143 default = "http://localhost:${toString cfg.settings.web.listen.port}"; 144 defaultText = literalExpression ''"http://localhost:''${config.services.scrutiny.settings.web.listen.port}"''; 145 description = "Scrutiny app API endpoint for sending metrics to."; 146 }; 147 148 options.log.level = mkOption { 149 type = enum [ "INFO" "DEBUG" ]; 150 default = "INFO"; 151 description = "Log level for Scrutiny collector."; 152 }; 153 }; 154 }; 155 }; 156 }; 157 }; 158 159 config = mkMerge [ 160 (mkIf cfg.enable { 161 services.influxdb2.enable = cfg.influxdb.enable; 162 163 networking.firewall = mkIf cfg.openFirewall { 164 allowedTCPPorts = [ cfg.settings.web.listen.port ]; 165 }; 166 167 systemd.services.scrutiny = { 168 description = "Hard Drive S.M.A.R.T Monitoring, Historical Trends & Real World Failure Thresholds"; 169 wantedBy = [ "multi-user.target" ]; 170 after = [ "network.target" ] ++ lib.optional cfg.influxdb.enable "influxdb2.service"; 171 wants = lib.optional cfg.influxdb.enable "influxdb2.service"; 172 environment = { 173 SCRUTINY_VERSION = "1"; 174 SCRUTINY_WEB_DATABASE_LOCATION = "/var/lib/scrutiny/scrutiny.db"; 175 SCRUTINY_WEB_SRC_FRONTEND_PATH = "${cfg.package}/share/scrutiny"; 176 }; 177 serviceConfig = { 178 DynamicUser = true; 179 ExecStart = "${getExe cfg.package} start --config ${settingsFormat.generate "scrutiny.yaml" cfg.settings}"; 180 Restart = "always"; 181 StateDirectory = "scrutiny"; 182 StateDirectoryMode = "0750"; 183 }; 184 }; 185 }) 186 (mkIf cfg.collector.enable { 187 services.smartd = { 188 enable = true; 189 extraOptions = [ 190 "-A /var/log/smartd/" 191 "--interval=600" 192 ]; 193 }; 194 195 systemd = { 196 services.scrutiny-collector = { 197 description = "Scrutiny Collector Service"; 198 after = lib.optional cfg.enable "scrutiny.service"; 199 wants = lib.optional cfg.enable "scrutiny.service"; 200 environment = { 201 COLLECTOR_VERSION = "1"; 202 COLLECTOR_API_ENDPOINT = cfg.collector.settings.api.endpoint; 203 }; 204 serviceConfig = { 205 Type = "oneshot"; 206 ExecStart = "${getExe cfg.collector.package} run --config ${settingsFormat.generate "scrutiny-collector.yaml" cfg.collector.settings}"; 207 }; 208 startAt = cfg.collector.schedule; 209 }; 210 211 timers.scrutiny-collector.timerConfig.Persistent = true; 212 }; 213 }) 214 ]; 215 216 meta.maintainers = [ maintainers.jnsgruk ]; 217}