{ config, lib, pkgs, ... }: let cfg = config.services.unpoller; configFile = pkgs.writeText "unpoller.json" (lib.generators.toJSON {} { inherit (cfg) poller influxdb loki prometheus unifi; }); in { imports = [ (lib.mkRenamedOptionModule [ "services" "unifi-poller" ] [ "services" "unpoller" ]) ]; options.services.unpoller = { enable = lib.mkEnableOption "unpoller"; poller = { debug = lib.mkOption { type = lib.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 = lib.mkOption { type = lib.types.bool; default = false; description = '' Turns off per-interval logs. Only startup and error logs will be emitted. ''; }; plugins = lib.mkOption { type = with lib.types; listOf str; default = []; description = '' Load additional plugins. ''; }; }; prometheus = { disable = lib.mkOption { type = lib.types.bool; default = false; description = '' Whether to disable the prometheus output plugin. ''; }; http_listen = lib.mkOption { type = lib.types.str; default = "[::]:9130"; description = '' Bind the prometheus exporter to this IP or hostname. ''; }; report_errors = lib.mkOption { type = lib.types.bool; default = false; description = '' Whether to report errors. ''; }; }; influxdb = { disable = lib.mkOption { type = lib.types.bool; default = false; description = '' Whether to disable the influxdb output plugin. ''; }; url = lib.mkOption { type = lib.types.str; default = "http://127.0.0.1:8086"; description = '' URL of the influxdb host. ''; }; user = lib.mkOption { type = lib.types.str; default = "unifipoller"; description = '' Username for the influxdb. ''; }; pass = lib.mkOption { type = lib.types.path; default = pkgs.writeText "unpoller-influxdb-default.password" "unifipoller"; defaultText = lib.literalExpression "unpoller-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 = lib.mkOption { type = lib.types.str; default = "unifi"; description = '' Database name. Database should exist. ''; }; verify_ssl = lib.mkOption { type = lib.types.bool; default = true; description = '' Verify the influxdb's certificate. ''; }; interval = lib.mkOption { type = lib.types.str; default = "30s"; description = '' Setting this lower than the Unifi controller's refresh interval may lead to zeroes in your database. ''; }; }; loki = { url = lib.mkOption { type = lib.types.str; default = ""; description = '' URL of the Loki host. ''; }; user = lib.mkOption { type = lib.types.str; default = ""; description = '' Username for Loki. ''; }; pass = lib.mkOption { type = lib.types.path; default = pkgs.writeText "unpoller-loki-default.password" ""; defaultText = "unpoller-influxdb-default.password"; description = '' Path of a file containing the password for Loki. This file needs to be readable by the unifi-poller user. ''; apply = v: "file://${v}"; }; verify_ssl = lib.mkOption { type = lib.types.bool; default = false; description = '' Verify Loki's certificate. ''; }; tenant_id = lib.mkOption { type = lib.types.str; default = ""; description = '' Tenant ID to use in Loki. ''; }; interval = lib.mkOption { type = lib.types.str; default = "2m"; description = '' How often the events are polled and pushed to Loki. ''; }; timeout = lib.mkOption { type = lib.types.str; default = "10s"; description = '' Should be increased in case of timeout errors. ''; }; }; unifi = let controllerOptions = { user = lib.mkOption { type = lib.types.str; default = "unifi"; description = '' Unifi service user name. ''; }; pass = lib.mkOption { type = lib.types.path; default = pkgs.writeText "unpoller-unifi-default.password" "unifi"; defaultText = lib.literalExpression "unpoller-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 = lib.mkOption { type = lib.types.str; default = "https://unifi:8443"; description = '' URL of the Unifi controller. ''; }; sites = lib.mkOption { type = with lib.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 = lib.toList; }; save_ids = lib.mkOption { type = lib.types.bool; default = false; description = '' Collect and save data from the intrusion detection system to influxdb and Loki. ''; }; save_events = lib.mkOption { type = lib.types.bool; default = false; description = '' Collect and save data from UniFi events to influxdb and Loki. ''; }; save_alarms = lib.mkOption { type = lib.types.bool; default = false; description = '' Collect and save data from UniFi alarms to influxdb and Loki. ''; }; save_anomalies = lib.mkOption { type = lib.types.bool; default = false; description = '' Collect and save data from UniFi anomalies to influxdb and Loki. ''; }; save_dpi = lib.mkOption { type = lib.types.bool; default = false; description = '' Collect and save data from deep packet inspection. Adds around 150 data points and impacts performance. ''; }; save_sites = lib.mkOption { type = lib.types.bool; default = true; description = '' Collect and save site data. ''; }; hash_pii = lib.mkOption { type = lib.types.bool; default = false; description = '' Hash, with md5, client names and MAC addresses. This attempts to protect personally identifiable information. ''; }; verify_ssl = lib.mkOption { type = lib.types.bool; default = true; description = '' Verify the Unifi controller's certificate. ''; }; }; in { dynamic = lib.mkOption { type = lib.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 = lib.mkOption { type = with lib.types; listOf (submodule { options = controllerOptions; }); default = []; description = '' List of Unifi controllers to poll. Use defaults if empty. ''; apply = map (lib.flip removeAttrs [ "_module" ]); }; }; }; config = lib.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.unpoller}/bin/unpoller --config ${configFile}"; Restart = "always"; PrivateTmp = true; ProtectHome = true; ProtectSystem = "full"; DevicePolicy = "closed"; NoNewPrivileges = true; User = "unifi-poller"; WorkingDirectory = "/tmp"; }; }; }; }