diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index b516b1785195..c54bc6098d3e 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -554,6 +554,7 @@ ./services/monitoring/telegraf.nix ./services/monitoring/thanos.nix ./services/monitoring/tuptime.nix + ./services/monitoring/unifi-poller.nix ./services/monitoring/ups.nix ./services/monitoring/uptime.nix ./services/monitoring/vnstat.nix diff --git a/nixos/modules/services/monitoring/unifi-poller.nix b/nixos/modules/services/monitoring/unifi-poller.nix new file mode 100644 index 000000000000..208f5e4875b4 --- /dev/null +++ b/nixos/modules/services/monitoring/unifi-poller.nix @@ -0,0 +1,242 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.unifi-poller; + + configFile = pkgs.writeText "unifi-poller.json" (generators.toJSON {} { + inherit (cfg) poller influxdb prometheus unifi; + }); + +in { + options.services.unifi-poller = { + enable = mkEnableOption "unifi-poller"; + + poller = { + debug = mkOption { + type = types.bool; + default = false; + description = '' + Turns on line numbers, microsecond logging, and a per-device log. + This may be noisy if you have a lot of devices. It adds one line per device. + ''; + }; + quiet = mkOption { + type = types.bool; + default = false; + description = '' + Turns off per-interval logs. Only startup and error logs will be emitted. + ''; + }; + plugins = mkOption { + type = with types; listOf str; + default = []; + description = '' + Load additional plugins. + ''; + }; + }; + + prometheus = { + disable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to disable the prometheus ouput plugin. + ''; + }; + http_listen = mkOption { + type = types.str; + default = "[::]:9130"; + description = '' + Bind the prometheus exporter to this IP or hostname. + ''; + }; + report_errors = mkOption { + type = types.bool; + default = false; + description = '' + Whether to report errors. + ''; + }; + }; + + influxdb = { + disable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to disable the influxdb ouput plugin. + ''; + }; + url = mkOption { + type = types.str; + default = "http://127.0.0.1:8086"; + description = '' + URL of the influxdb host. + ''; + }; + user = mkOption { + type = types.str; + default = "unifipoller"; + description = '' + Username for the influxdb. + ''; + }; + pass = mkOption { + type = types.path; + default = pkgs.writeText "unifi-poller-influxdb-default.password" "unifipoller"; + defaultText = "unifi-poller-influxdb-default.password"; + description = '' + Path of a file containing the password for influxdb. + This file needs to be readable by the unifi-poller user. + ''; + apply = v: "file://${v}"; + }; + db = mkOption { + type = types.str; + default = "unifi"; + description = '' + Database name. Database should exist. + ''; + }; + verify_ssl = mkOption { + type = types.bool; + default = true; + description = '' + Verify the influxdb's certificate. + ''; + }; + interval = mkOption { + type = types.str; + default = "30s"; + description = '' + Setting this lower than the Unifi controller's refresh + interval may lead to zeroes in your database. + ''; + }; + }; + + unifi = let + controllerOptions = { + user = mkOption { + type = types.str; + default = "unifi"; + description = '' + Unifi service user name. + ''; + }; + pass = mkOption { + type = types.path; + default = pkgs.writeText "unifi-poller-unifi-default.password" "unifi"; + defaultText = "unifi-poller-unifi-default.password"; + description = '' + Path of a file containing the password for the unifi service user. + This file needs to be readable by the unifi-poller user. + ''; + apply = v: "file://${v}"; + }; + url = mkOption { + type = types.str; + default = "https://unifi:8443"; + description = '' + URL of the Unifi controller. + ''; + }; + sites = mkOption { + type = with types; either (enum [ "default" "all" ]) (listOf str); + default = "all"; + description = '' + List of site names for which statistics should be exported. + Or the string "default" for the default site or the string "all" for all sites. + ''; + apply = toList; + }; + save_ids = mkOption { + type = types.bool; + default = false; + description = '' + Collect and save data from the intrusion detection system to influxdb. + ''; + }; + save_dpi = mkOption { + type = types.bool; + default = false; + description = '' + Collect and save data from deep packet inspection. + Adds around 150 data points and impacts performance. + ''; + }; + save_sites = mkOption { + type = types.bool; + default = true; + description = '' + Collect and save site data. + ''; + }; + hash_pii = mkOption { + type = types.bool; + default = false; + description = '' + Hash, with md5, client names and MAC addresses. This attempts + to protect personally identifiable information. + ''; + }; + verify_ssl = mkOption { + type = types.bool; + default = true; + description = '' + Verify the Unifi controller's certificate. + ''; + }; + }; + + in { + dynamic = mkOption { + type = types.bool; + default = false; + description = '' + Let prometheus select which controller to poll when scraping. + Use with default credentials. See unifi-poller wiki for more. + ''; + }; + + defaults = controllerOptions; + + controllers = mkOption { + type = with types; listOf (submodule { options = controllerOptions; }); + default = []; + description = '' + List of Unifi controllers to poll. Use defaults if empty. + ''; + apply = map (flip removeAttrs [ "_module" ]); + }; + }; + }; + + config = mkIf cfg.enable { + users.groups.unifi-poller = { }; + users.users.unifi-poller = { + description = "unifi-poller Service User"; + group = "unifi-poller"; + isSystemUser = true; + }; + + systemd.services.unifi-poller = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + ExecStart = "${pkgs.unifi-poller}/bin/unifi-poller --config ${configFile}"; + Restart = "always"; + PrivateTmp = true; + ProtectHome = true; + ProtectSystem = "full"; + DevicePolicy = "closed"; + NoNewPrivileges = true; + User = "unifi-poller"; + WorkingDirectory = "/tmp"; + }; + }; + }; +}