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