package: { config, lib, pkgs, ... }: let tempSensorOptions = (import ./submodules/tempSensorOptions.nix) { inherit lib; }; vulnixWhitelistRule = (import ./submodules/vulnixWhitelistRule.nix) { inherit lib; }; in { options.services.lego-monitoring = { enable = lib.mkEnableOption "lego-monitoring service."; enabledCheckSets = lib.mkOption { type = lib.types.listOf (lib.types.enum [ "start" "stop" "temp" "vulnix" ]); default = [ ]; description = "List of enabled check sets. Each check set is a module which checks something and generates alerts based on check results."; }; telegram = { credsSecretPath = lib.mkOption { type = lib.types.str; description = "Path to a file containing Telegram api_id, api_hash, and bot token, separated by the `,` character."; }; roomId = lib.mkOption { type = lib.types.int; description = "ID of chat where to send alerts."; }; }; checks = { temp = { sensors = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule tempSensorOptions); default = { }; description = '' Temp sensor override definitions. Sensors not defined here, or missing options in definitions, will be read with default parameters. To get list of sensors and their default configurations, run `lego-monitoring --print-temp`.''; example = lib.literalExpression '' { amdgpu.readings.edge.label = "Integrated GPU"; k10temp.readings = { Tctl = { label = "AMD CPU"; criticalTemp = 95.0; }; Tccd1.enabled = false; Tccd2.enabled = false; }; nvme.readings = { "Sensor 1".enabled = false; "Sensor 2".enabled = false; }; } ''; }; }; vulnix = { whitelist = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule vulnixWhitelistRule); default = { }; description = "Whitelist rules for vulnix. Attr name is package with version, package name, or `*`."; example = lib.literalExpression ''{ "ffmpeg-3.4.2" = { cve = [ "CVE-2018-6912" "CVE-2018-7557" ]; until = "2018-05-01"; issueUrl = "https://issues.example.com/29952"; }; }''; }; }; }; }; config = let cfg = config.services.lego-monitoring; json = pkgs.formats.json {}; toml = pkgs.formats.toml {}; # This monstrous incantation has the effect of converting the options to snake_case # and removing those that are null (because TOML does not support null values) vulnixWhitelistFile = toml.generate "vulnix-whitelist.toml" (lib.attrsets.filterAttrsRecursive ( k: v: v != null ) ( lib.mapAttrs (_: rule: { inherit (rule) cve until; issue_url = rule.issueUrl; }) cfg.checks.vulnix.whitelist )); serviceConfigFile = json.generate "config.json" { enabled_check_sets = cfg.enabledCheckSets; telegram = with cfg.telegram; { creds_secret_path = credsSecretPath; room_id = roomId; }; checks = { temp.sensors = lib.mapAttrs (_: sensorCfg: { inherit (sensorCfg) name enabled; readings = lib.mapAttrs (_: readingCfg: { inherit (readingCfg) label enabled; warning_temp = readingCfg.warningTemp; critical_temp = readingCfg.criticalTemp; }) sensorCfg.readings; }) cfg.checks.temp.sensors; vulnix.whitelist_path = vulnixWhitelistFile; }; }; in lib.mkIf cfg.enable { systemd.services.lego-monitoring = { name = "lego-monitoring.service"; description = "Lego-monitoring service"; script = "${package}/bin/lego-monitoring -c ${serviceConfigFile}"; wantedBy = [ "multi-user.target" ]; }; }; }