at 24.11-pre 9.0 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.unpoller; 7 8 configFile = pkgs.writeText "unpoller.json" (generators.toJSON {} { 9 inherit (cfg) poller influxdb loki prometheus unifi; 10 }); 11 12in { 13 imports = [ 14 (lib.mkRenamedOptionModule [ "services" "unifi-poller" ] [ "services" "unpoller" ]) 15 ]; 16 17 options.services.unpoller = { 18 enable = mkEnableOption "unpoller"; 19 20 poller = { 21 debug = mkOption { 22 type = types.bool; 23 default = false; 24 description = '' 25 Turns on line numbers, microsecond logging, and a per-device log. 26 This may be noisy if you have a lot of devices. It adds one line per device. 27 ''; 28 }; 29 quiet = mkOption { 30 type = types.bool; 31 default = false; 32 description = '' 33 Turns off per-interval logs. Only startup and error logs will be emitted. 34 ''; 35 }; 36 plugins = mkOption { 37 type = with types; listOf str; 38 default = []; 39 description = '' 40 Load additional plugins. 41 ''; 42 }; 43 }; 44 45 prometheus = { 46 disable = mkOption { 47 type = types.bool; 48 default = false; 49 description = '' 50 Whether to disable the prometheus output plugin. 51 ''; 52 }; 53 http_listen = mkOption { 54 type = types.str; 55 default = "[::]:9130"; 56 description = '' 57 Bind the prometheus exporter to this IP or hostname. 58 ''; 59 }; 60 report_errors = mkOption { 61 type = types.bool; 62 default = false; 63 description = '' 64 Whether to report errors. 65 ''; 66 }; 67 }; 68 69 influxdb = { 70 disable = mkOption { 71 type = types.bool; 72 default = false; 73 description = '' 74 Whether to disable the influxdb output plugin. 75 ''; 76 }; 77 url = mkOption { 78 type = types.str; 79 default = "http://127.0.0.1:8086"; 80 description = '' 81 URL of the influxdb host. 82 ''; 83 }; 84 user = mkOption { 85 type = types.str; 86 default = "unifipoller"; 87 description = '' 88 Username for the influxdb. 89 ''; 90 }; 91 pass = mkOption { 92 type = types.path; 93 default = pkgs.writeText "unpoller-influxdb-default.password" "unifipoller"; 94 defaultText = literalExpression "unpoller-influxdb-default.password"; 95 description = '' 96 Path of a file containing the password for influxdb. 97 This file needs to be readable by the unifi-poller user. 98 ''; 99 apply = v: "file://${v}"; 100 }; 101 db = mkOption { 102 type = types.str; 103 default = "unifi"; 104 description = '' 105 Database name. Database should exist. 106 ''; 107 }; 108 verify_ssl = mkOption { 109 type = types.bool; 110 default = true; 111 description = '' 112 Verify the influxdb's certificate. 113 ''; 114 }; 115 interval = mkOption { 116 type = types.str; 117 default = "30s"; 118 description = '' 119 Setting this lower than the Unifi controller's refresh 120 interval may lead to zeroes in your database. 121 ''; 122 }; 123 }; 124 125 loki = { 126 url = mkOption { 127 type = types.str; 128 default = ""; 129 description = '' 130 URL of the Loki host. 131 ''; 132 }; 133 user = mkOption { 134 type = types.str; 135 default = ""; 136 description = '' 137 Username for Loki. 138 ''; 139 }; 140 pass = mkOption { 141 type = types.path; 142 default = pkgs.writeText "unpoller-loki-default.password" ""; 143 defaultText = "unpoller-influxdb-default.password"; 144 description = '' 145 Path of a file containing the password for Loki. 146 This file needs to be readable by the unifi-poller user. 147 ''; 148 apply = v: "file://${v}"; 149 }; 150 verify_ssl = mkOption { 151 type = types.bool; 152 default = false; 153 description = '' 154 Verify Loki's certificate. 155 ''; 156 }; 157 tenant_id = mkOption { 158 type = types.str; 159 default = ""; 160 description = '' 161 Tenant ID to use in Loki. 162 ''; 163 }; 164 interval = mkOption { 165 type = types.str; 166 default = "2m"; 167 description = '' 168 How often the events are polled and pushed to Loki. 169 ''; 170 }; 171 timeout = mkOption { 172 type = types.str; 173 default = "10s"; 174 description = '' 175 Should be increased in case of timeout errors. 176 ''; 177 }; 178 }; 179 180 unifi = let 181 controllerOptions = { 182 user = mkOption { 183 type = types.str; 184 default = "unifi"; 185 description = '' 186 Unifi service user name. 187 ''; 188 }; 189 pass = mkOption { 190 type = types.path; 191 default = pkgs.writeText "unpoller-unifi-default.password" "unifi"; 192 defaultText = literalExpression "unpoller-unifi-default.password"; 193 description = '' 194 Path of a file containing the password for the unifi service user. 195 This file needs to be readable by the unifi-poller user. 196 ''; 197 apply = v: "file://${v}"; 198 }; 199 url = mkOption { 200 type = types.str; 201 default = "https://unifi:8443"; 202 description = '' 203 URL of the Unifi controller. 204 ''; 205 }; 206 sites = mkOption { 207 type = with types; either (enum [ "default" "all" ]) (listOf str); 208 default = "all"; 209 description = '' 210 List of site names for which statistics should be exported. 211 Or the string "default" for the default site or the string "all" for all sites. 212 ''; 213 apply = toList; 214 }; 215 save_ids = mkOption { 216 type = types.bool; 217 default = false; 218 description = '' 219 Collect and save data from the intrusion detection system to influxdb and Loki. 220 ''; 221 }; 222 save_events = mkOption { 223 type = types.bool; 224 default = false; 225 description = '' 226 Collect and save data from UniFi events to influxdb and Loki. 227 ''; 228 }; 229 save_alarms = mkOption { 230 type = types.bool; 231 default = false; 232 description = '' 233 Collect and save data from UniFi alarms to influxdb and Loki. 234 ''; 235 }; 236 save_anomalies = mkOption { 237 type = types.bool; 238 default = false; 239 description = '' 240 Collect and save data from UniFi anomalies to influxdb and Loki. 241 ''; 242 }; 243 save_dpi = mkOption { 244 type = types.bool; 245 default = false; 246 description = '' 247 Collect and save data from deep packet inspection. 248 Adds around 150 data points and impacts performance. 249 ''; 250 }; 251 save_sites = mkOption { 252 type = types.bool; 253 default = true; 254 description = '' 255 Collect and save site data. 256 ''; 257 }; 258 hash_pii = mkOption { 259 type = types.bool; 260 default = false; 261 description = '' 262 Hash, with md5, client names and MAC addresses. This attempts 263 to protect personally identifiable information. 264 ''; 265 }; 266 verify_ssl = mkOption { 267 type = types.bool; 268 default = true; 269 description = '' 270 Verify the Unifi controller's certificate. 271 ''; 272 }; 273 }; 274 275 in { 276 dynamic = mkOption { 277 type = types.bool; 278 default = false; 279 description = '' 280 Let prometheus select which controller to poll when scraping. 281 Use with default credentials. See unifi-poller wiki for more. 282 ''; 283 }; 284 285 defaults = controllerOptions; 286 287 controllers = mkOption { 288 type = with types; listOf (submodule { options = controllerOptions; }); 289 default = []; 290 description = '' 291 List of Unifi controllers to poll. Use defaults if empty. 292 ''; 293 apply = map (flip removeAttrs [ "_module" ]); 294 }; 295 }; 296 }; 297 298 config = mkIf cfg.enable { 299 users.groups.unifi-poller = { }; 300 users.users.unifi-poller = { 301 description = "unifi-poller Service User"; 302 group = "unifi-poller"; 303 isSystemUser = true; 304 }; 305 306 systemd.services.unifi-poller = { 307 wantedBy = [ "multi-user.target" ]; 308 after = [ "network.target" ]; 309 serviceConfig = { 310 ExecStart = "${pkgs.unpoller}/bin/unpoller --config ${configFile}"; 311 Restart = "always"; 312 PrivateTmp = true; 313 ProtectHome = true; 314 ProtectSystem = "full"; 315 DevicePolicy = "closed"; 316 NoNewPrivileges = true; 317 User = "unifi-poller"; 318 WorkingDirectory = "/tmp"; 319 }; 320 }; 321 }; 322}