diff --git a/nix/lib/lists.nix b/nix/lib/lists.nix new file mode 100644 index 0000000..370362f --- /dev/null +++ b/nix/lib/lists.nix @@ -0,0 +1,13 @@ +let + inherit (builtins) length tail; +in +{ + flake.lib.lists = rec { + shortenList = + count: list: + let + len = length list; + in + if len <= count then list else (shortenList count (tail list)); + }; +} diff --git a/nix/lib/options.nix b/nix/lib/options.nix index a7c873c..4d0c329 100644 --- a/nix/lib/options.nix +++ b/nix/lib/options.nix @@ -1,7 +1,13 @@ { lib, ... }: let inherit (lib.options) mkOption; - inherit (lib.types) str; + inherit (lib.types) + str + path + int + port + attrs + ; in { flake.lib.options = { @@ -11,5 +17,29 @@ in inherit default; type = str; }; + mkAttrOption = + default: + mkOption { + inherit default; + type = attrs; + }; + mkIntOption = + default: + mkOption { + inherit default; + type = int; + }; + mkPortOption = + default: + mkOption { + type = port; + inherit default; + }; + mkPathOption = + default: + mkOption { + type = path; + inherit default; + }; }; } diff --git a/nix/lib/services.nix b/nix/lib/services.nix new file mode 100644 index 0000000..879551d --- /dev/null +++ b/nix/lib/services.nix @@ -0,0 +1,60 @@ +{ config, lib, ... }: +let + inherit (builtins) length concatStringsSep; + inherit (lib.options) mkEnableOption; + inherit (lib.strings) splitString; + inherit (lib.lists) singleton; + inherit (lib.modules) mkMerge mkIf; + inherit (cfg.lib.options) mkStrOption mkPortOption mkAttrOption; + inherit (cfg.lib.lists) shortenList; + cfg = config.flake; +in +{ + flake.lib.services = rec { + splitDomain = domain: splitString "." domain; + isRootDomain = domain: length (splitDomain domain) <= 2; + mkRootDomain = domain: concatStringsSep "." (shortenList 2 (splitDomain domain)); + mkWildcardDomain = rootDomain: concatStringsSep "." ((singleton "*") ++ (splitDomain rootDomain)); + mkHost = domain: if isRootDomain domain then domain else mkWildcardDomain (mkRootDomain domain); + mkWebApp = + { + name, + defaultPort, + persistDirs ? [ ], + serviceConfig ? { }, + extraOptions ? { }, + }: + let + cfg = config.server.web-apps.${name}; + in + { + options.server.web-apps.${name} = { + enable = mkEnableOption ""; + port = mkPortOption defaultPort; + domain = mkStrOption ""; + openFirewall = mkEnableOption ""; + extraCfg = mkAttrOption { }; + } // extraOptions; + + config = mkIf cfg.enable (mkMerge [ + { + inherit persistDirs; + networking.firewall = mkIf cfg.openFirewall { allowedTCPPorts = singleton cfg.port; }; + } + (mkIf (cfg.domain != "") { + assertions = singleton { + assertion = config.server.web-servers.nginx.enable; + message = "You must enable a web server if you want to set server.web-apps.${name}.domain."; + }; + server.networking.ddns.domains = singleton (mkRootDomain cfg.domain); + server.web-servers.nginx.proxies = singleton { + source = cfg.domain; + target = "http://${config.hostname}:${toString cfg.port}"; + }; + }) + serviceConfig + cfg.extraCfg + ]); + }; + }; +}