{ inputs = { environment.url = "path:../environment"; secrets.url = "path:../../secrets"; naemon.url = "path:../../naemon"; nixpkgs-lib.url = "github:NixOS/nixpkgs?dir=lib"; }; outputs = { self, environment, nixpkgs-lib, secrets, naemon }: { nagios-cli-config = ./nagios-cli.cfg; lib = rec { expandedObject = kind: object: objects: if object ? "use" then expandedObject kind objects.templates.${kind}.${object.use} objects // object else object; objectsCommon = import ./objects_common.nix; toObjects = import ./to_objects.nix { inherit (nixpkgs-lib) lib; }; toMasterPassiveObject = svcTemplate: freshnessThresholdMultiplier: objects: { service = with nixpkgs-lib.lib; map (s: { host_name = (expandedObject "service" s objects).host_name; use = svcTemplate; retry_interval = "1"; freshness_threshold = let fs = expandedObject "service" s objects; in if builtins.isInt fs.check_interval then builtins.ceil (freshnessThresholdMultiplier * 60 * fs.check_interval) else fs.check_interval; } // filterAttrs (k: v: builtins.elem k ["service_description"] || builtins.substring 0 1 k == "_") s // mapAttrs' (n: nameValuePair (removePrefix "__passive_" n)) (filterAttrs (k: _: hasPrefix "__passive_" k) s) ) objects.service; host = objects.host; }; emailCheck = allCfg: host: hostFQDN: let cfg = allCfg."${host}"; reverseTargets = builtins.attrNames (nixpkgs-lib.lib.filterAttrs (k: v: builtins.elem host v.targets) allCfg); to_email = cfg': host': let sep = if nixpkgs-lib.lib.hasInfix "+" cfg'.mail_address then "_" else "+"; in "${cfg'.mail_address}${sep}${host'}@${cfg'.mail_domain}"; mails_to_send = builtins.concatStringsSep "," (map (n: to_email allCfg."${n}" host) cfg.targets); mails_to_receive = builtins.concatStringsSep "," (map (n: "${to_email cfg n}:${n}") reverseTargets); command = if cfg.local then [ "check_emails_local" "/var/lib/naemon/checks/email" mails_to_send mails_to_receive ] else [ "check_emails" cfg.login cfg.port mails_to_send mails_to_receive ]; in { service_description = "${hostFQDN} email service is active"; use = "mail-service"; host_name = hostFQDN; servicegroups = "webstatus-email"; check_command = command; }; }; nixosModule = self.nixosModules.monitoring; nixosModules.monitoring = { config, pkgs, lib, ... }: let cfg = config.myServices.monitoring; allPluginsConfig = import ./myplugins.nix { inherit pkgs lib config; sudo = "/run/wrappers/bin/sudo"; }; mypluginsConfig = lib.mapAttrs (n: v: if builtins.isFunction v then v (cfg.pluginsArgs."${n}" or {}) else v ) (lib.getAttrs cfg.activatedPlugins allPluginsConfig); myplugins = let mypluginsChunk = builtins.concatStringsSep "\n" (lib.mapAttrsToList (k: v: v.chunk or "") mypluginsConfig); in pkgs.runCommand "buildplugins" { buildInputs = [ pkgs.makeWrapper pkgs.perl ]; } '' mkdir $out ${mypluginsChunk} ''; objectsModule = with lib.types; submodule { options = { command = lib.mkOption { type = attrsOf str; default = {}; description = "Command definitions"; }; host = lib.mkOption { type = attrsOf (attrsOf str); default = {}; description = "Host definitions"; }; hostgroup = lib.mkOption { type = attrsOf (attrsOf str); default = {}; description = "Host group definitions"; }; hostdependency = lib.mkOption { type = listOf (attrsOf str); default = []; description = "Host dependency definitions"; }; service = lib.mkOption { type = listOf (attrsOf (oneOf [ str (listOf str) int ])); # str -> string # listOf str -> list to be concatenated with "!" # int -> toString default = []; description = "Service definitions"; }; servicegroup = lib.mkOption { type = attrsOf (attrsOf str); default = {}; description = "Service group definitions"; }; servicedependency = lib.mkOption { type = listOf (attrsOf str); default = []; description = "Service dependency definitions"; }; contact = lib.mkOption { type = attrsOf (attrsOf str); default = {}; description = "Contact definitions"; }; contactgroup = lib.mkOption { type = attrsOf (attrsOf str); default = {}; description = "Contact group definitions"; }; timeperiod = lib.mkOption { type = attrsOf (attrsOf str); default = {}; description = "Time period definitions"; }; templates = lib.mkOption { description = "Template definitions"; default = {}; type = submodule { options = { service = lib.mkOption { type = attrsOf (attrsOf (either str int)); default = {}; }; contact = lib.mkOption { type = attrsOf (attrsOf str); default = {}; }; host = lib.mkOption { type = attrsOf (attrsOf str); default = {}; }; }; }; }; }; }; in { options = { myServices.monitoring = { enable = lib.mkOption { type = lib.types.bool; default = false; description = '' Whether to enable monitoring. ''; }; master = lib.mkOption { type = lib.types.bool; default = false; description = '' This instance is the master instance ''; }; pluginsArgs = lib.mkOption { default = {}; description = "Arguments to pass to the naemon plugin configuration"; type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); }; activatedPlugins = lib.mkOption { default = []; description = "List of naemon plugins to activate"; type = lib.types.listOf (lib.types.enum (builtins.attrNames allPluginsConfig)); }; fromMasterActivatedPlugins = lib.mkOption { default = []; description = "List of naemon plugins to activate from master"; type = lib.types.listOf (lib.types.str); }; resources = lib.mkOption { default = {}; description = "List of additionnal resources elements"; type = lib.types.attrsOf (lib.types.str); }; objects = lib.mkOption { default = {}; description = "Object definitions"; type = objectsModule; }; fromMasterObjects = lib.mkOption { default = {}; description = "Object definitions of checks that should be executed from master"; type = objectsModule; }; }; }; imports = [ environment.nixosModule secrets.nixosModule naemon.nixosModule ]; config = lib.mkIf cfg.enable { myServices.monitoring.objects.command = lib.foldr (v: o: o // (v.commands or {})) {} (builtins.attrValues mypluginsConfig); security.sudo.extraRules = let pluginsSudo = lib.lists.remove null (lib.mapAttrsToList (k: v: if (v ? sudo) then ({ users = [ "naemon" ]; } // (v.sudo myplugins)) else null) mypluginsConfig); in pluginsSudo; environment.etc.cnagios.source = "${pkgs.cnagios}/share/doc/cnagios"; environment.systemPackages = let nagios-cli = pkgs.writeScriptBin "nagios-cli" '' #!${pkgs.stdenv.shell} sudo -u naemon ${pkgs.nagios-cli}/bin/nagios-cli -c ${self.nagios-cli-config} ''; in [ pkgs.cnagios nagios-cli ]; secrets.keys = { "naemon/id_rsa" = { user = "naemon"; group = "naemon"; permissions = "0400"; text = config.myEnv.monitoring.ssh_secret_key; }; "naemon/resources.cfg".keyDependencies = [ myplugins ]; }; services.naemon = { enable = true; extraConfig = '' use_syslog=1 log_initial_states=1 date_format=iso8601 admin_email=${config.myEnv.monitoring.email} '' + lib.optionalString (!cfg.master) '' obsess_over_services=1 ocsp_command=notify-master ''; extraResource = let resources = [cfg.resources or {}] ++ (lib.mapAttrsToList (k: v: v.resources or {}) mypluginsConfig); joined = lib.zipAttrsWith (n: v: if builtins.length (lib.unique v) == 1 then builtins.head v else abort "Non-unique resources names") resources; joinedStr = builtins.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "$" + "${k}$=${v}") joined); in '' $USER2$=${myplugins} ${joinedStr} ''; objectDefs = self.lib.toObjects cfg.objects; }; }; }; }; }