{ config, lib, pkgs, ... }: let cfg = config.my.services.unifi; secrets = config.age.secrets; allowedRules = { # https://help.ubnt.com/hc/en-us/articles/218506997 allowedTCPPorts = [ 8080 # Port for UAP to inform controller. 8880 # Port for HTTP portal redirect, if guest portal is enabled. 8843 # Port for HTTPS portal redirect, ditto. 6789 # Port for UniFi mobile speed test. 9130 # Port for the prometheus exporter ]; allowedUDPPorts = [ 3478 # UDP port used for STUN. 10001 # UDP port used for device discovery. ]; }; in { options.my.services.unifi = with lib; { enable = mkEnableOption "Unifi controller"; vhostName = mkOption { type = types.str; example = "music.fcuny.net"; description = "Name for the virtual host"; }; }; config = lib.mkIf cfg.enable { networking.firewall = allowedRules; users.users.unifi.group = "unifi"; users.users.unifi.isSystemUser = true; users.groups.unifi = { }; services.unifi = { enable = true; openFirewall = true; unifiPackage = pkgs.unifi7; mongodbPackage = pkgs.mongodb-4_2; }; services.nginx.virtualHosts."${cfg.vhostName}" = { forceSSL = true; useACMEHost = cfg.vhostName; listen = [ { addr = "100.85.232.66"; port = 443; ssl = true; } { addr = "100.85.232.66"; port = 80; ssl = false; } ]; locations."/" = { proxyPass = "https://127.0.0.1:8443"; proxyWebsockets = true; }; }; security.acme.certs."${cfg.vhostName}" = { dnsProvider = "gcloud"; credentialsFile = secrets."acme/credentials".path; }; my.services.backup = { paths = [ "/var/lib/unifi/data/backup" ]; }; }; }