diff --git a/nixos/access/unifi.nix b/nixos/access/unifi.nix new file mode 100644 index 00000000..45a4fb41 --- /dev/null +++ b/nixos/access/unifi.nix @@ -0,0 +1,99 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault; + inherit (lib.lists) concatMap; + inherit (config.services) nginx tailscale unifi; + access = nginx.access.unifi; +in { + options.services.nginx.access.unifi = with lib.types; { + global.enable = mkEnableOption "global access" // { + default = access.useACMEHost != null; + }; + host = mkOption { + type = str; + }; + url = mkOption { + type = str; + default = "https://${access.host}:${toString access.managementPort}"; + }; + managementPort = mkOption { + type = port; + default = 8443; + }; + domain = mkOption { + type = str; + default = "unifi.${config.networking.domain}"; + }; + localDomain = mkOption { + type = str; + default = "unifi.local.${config.networking.domain}"; + }; + tailDomain = mkOption { + type = str; + default = "unifi.tail.${config.networking.domain}"; + }; + useACMEHost = mkOption { + type = nullOr str; + default = null; + }; + }; + config.services.nginx = { + access.unifi = mkIf unifi.enable { + host = mkOptionDefault "localhost"; + }; + virtualHosts = let + extraConfig = '' + proxy_redirect off; + proxy_buffering off; + ''; + locations = { + "/" = { + proxyPass = access.url; + }; + }; + streamListen = { config, ... }: { + listen = concatMap (addr: [ + { + inherit addr; + port = 80; + ssl = false; + } + (mkIf (config.addSSL || config.forceSSL) { + inherit addr; + port = 443; + ssl = true; + }) + (mkIf (config.addSSL || config.forceSSL) { + inherit addr; + port = access.managementPort; + ssl = true; + }) + ]) nginx.defaultListenAddresses; + }; + in { + ${access.domain} = mkIf access.global.enable (mkMerge [ { + vouch.enable = true; + forceSSL = mkDefault true; + kTLS = mkDefault true; + useACMEHost = mkDefault access.useACMEHost; + inherit locations extraConfig; + } streamListen ]); + ${access.localDomain} = mkMerge [ { + serverAliases = mkIf tailscale.enable [ access.tailDomain ]; + useACMEHost = mkDefault access.useACMEHost; + addSSL = mkDefault (access.useACMEHost != null); + kTLS = mkDefault true; + local.enable = true; + inherit locations extraConfig; + } streamListen ]; + }; + }; + config.networking.firewall = { + interfaces.local.allowedTCPPorts = [ access.managementPort ]; + allowedTCPPorts = mkIf access.global.enable [ access.managementPort ]; + }; +} diff --git a/nixos/unifi.nix b/nixos/unifi.nix new file mode 100644 index 00000000..fee06b44 --- /dev/null +++ b/nixos/unifi.nix @@ -0,0 +1,32 @@ +{ + pkgs, + config, + lib, + ... +}: let + inherit (lib.modules) mkIf mkMerge mkDefault; + cfg = config.services.unifi; +in { + services.unifi = { + enable = mkDefault true; + unifiPackage = mkDefault pkgs.unifi8; + }; + + networking.firewall.interfaces.local = mkIf cfg.enable { + allowedTCPPorts = mkMerge [ + [ + 8443 # remote login + ] + (mkIf (!cfg.openFirewall) [ + 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. + ]) + ]; + allowedUDPPorts = mkIf (!cfg.openFirewall) [ + 3478 # UDP port used for STUN. + 10001 # UDP port used for device discovery. + ]; + }; +} diff --git a/systems/hakurei/nixos.nix b/systems/hakurei/nixos.nix index 57a245fd..4c701aa5 100644 --- a/systems/hakurei/nixos.nix +++ b/systems/hakurei/nixos.nix @@ -31,6 +31,7 @@ in { nixos.access.vouch nixos.access.kanidm nixos.access.freeipa + nixos.access.unifi nixos.access.kitchencam nixos.access.proxmox nixos.access.plex @@ -84,6 +85,15 @@ in { ]) ]; }; + ${access.unifi.domain} = { + inherit (nginx) group; + extraDomainNames = mkMerge [ + [access.unifi.localDomain] + (mkIf tailscale.enable [ + access.unifi.tailDomain + ]) + ]; + }; ${access.freeipa.domain} = { inherit (nginx) group; extraDomainNames = mkMerge [ @@ -151,6 +161,10 @@ in { host = tei.lib.access.hostnameForNetwork.local; ldapEnable = false; }; + access.unifi = { + host = tei.lib.access.hostnameForNetwork.local; + useACMEHost = access.unifi.domain; + }; access.freeipa = { host = "idp.local.${config.networking.domain}"; }; diff --git a/systems/tei/nixos.nix b/systems/tei/nixos.nix index c4505b0e..c914f42b 100644 --- a/systems/tei/nixos.nix +++ b/systems/tei/nixos.nix @@ -20,6 +20,7 @@ in { nixos.access.home-assistant nixos.vouch nixos.kanidm + nixos.unifi nixos.mosquitto nixos.home-assistant nixos.zigbee2mqtt diff --git a/tf/cloudflare_records.tf b/tf/cloudflare_records.tf index ecd6c683..06c32e83 100644 --- a/tf/cloudflare_records.tf +++ b/tf/cloudflare_records.tf @@ -21,6 +21,7 @@ module "hakurei_system_records" { "login", "ldap", "freeipa", + "unifi", "smb", "kitchen", "yt", @@ -29,6 +30,7 @@ module "hakurei_system_records" { "plex", "idp", "ldap", + "unifi", "smb", "kitchen", "yt",