X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=modules%2Fwebsites%2Fdefault.nix;h=4b21efb75eb386e97a42068313080d132e29cf05;hb=17f6eae9907a122d4472da727ae8b1ac1c40c027;hp=6a18c8afb1829f153ea852ee225f67dac9f1fb7a;hpb=daf64e3f7de98e4267823d14fa34891b27b5f657;p=perso%2FImmae%2FConfig%2FNix.git diff --git a/modules/websites/default.nix b/modules/websites/default.nix index 6a18c8a..4b21efb 100644 --- a/modules/websites/default.nix +++ b/modules/websites/default.nix @@ -3,6 +3,9 @@ let cfg = config.services.websites; in { + options.services.websitesCerts = mkOption { + description = "Default websites configuration for certificates as accepted by acme"; + }; options.services.websites = with types; mkOption { default = {}; description = "Each type of website to enable will target a distinct httpd server"; @@ -72,12 +75,29 @@ in type = attrsOf (submodule { options = { certName = mkOption { type = string; }; + addToCerts = mkOption { + type = bool; + default = false; + description = "Use these to certificates. Is ignored (considered true) if certMainHost is not null"; + }; + certMainHost = mkOption { + type = nullOr string; + description = "Use that host as 'main host' for acme certs"; + default = null; + }; hosts = mkOption { type = listOf string; }; root = mkOption { type = nullOr path; }; extraConfig = mkOption { type = listOf lines; default = []; }; }; }); }; + watchPaths = mkOption { + type = listOf string; + default = []; + description = '' + Paths to watch that should trigger a reload of httpd + ''; + }; }; }); }; @@ -89,7 +109,7 @@ in serverAliases = [ "*" ]; enableSSL = false; logFormat = "combinedVhost"; - documentRoot = "/var/lib/acme/acme-challenge"; + documentRoot = "${config.security.acme.directory}/acme-challenge"; extraConfig = '' RewriteEngine on RewriteCond "%{REQUEST_URI}" "!^/\.well-known" @@ -118,9 +138,9 @@ in }; toVhost = ips: vhostConf: { enableSSL = true; - sslServerCert = "/var/lib/acme/${vhostConf.certName}/cert.pem"; - sslServerKey = "/var/lib/acme/${vhostConf.certName}/key.pem"; - sslServerChain = "/var/lib/acme/${vhostConf.certName}/chain.pem"; + sslServerCert = "${config.security.acme.directory}/${vhostConf.certName}/cert.pem"; + sslServerKey = "${config.security.acme.directory}/${vhostConf.certName}/key.pem"; + sslServerChain = "${config.security.acme.directory}/${vhostConf.certName}/chain.pem"; logFormat = "combinedVhost"; listen = map (ip: { inherit ip; port = 443; }) ips; hostName = builtins.head vhostConf.hosts; @@ -145,4 +165,49 @@ in ++ [ (redirectVhost icfg.ips) ]; }) ) cfg; + + config.services.filesWatcher = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair + "httpd${icfg.httpdName}" { + paths = icfg.watchPaths; + waitTime = 5; + } + ) cfg; + + config.security.acme.certs = let + typesToManage = attrsets.filterAttrs (k: v: v.enable) cfg; + flatVhosts = lists.flatten (attrsets.mapAttrsToList (k: v: + attrValues v.vhostConfs + ) typesToManage); + groupedCerts = attrsets.filterAttrs + (_: group: builtins.any (v: v.addToCerts || !isNull v.certMainHost) group) + (lists.groupBy (v: v.certName) flatVhosts); + groupToDomain = group: + let + nonNull = builtins.filter (v: !isNull v.certMainHost) group; + domains = lists.unique (map (v: v.certMainHost) nonNull); + in + if builtins.length domains == 0 + then null + else assert (builtins.length domains == 1); (elemAt domains 0); + extraDomains = group: + let + mainDomain = groupToDomain group; + in + lists.remove mainDomain ( + lists.unique ( + lists.flatten (map (c: optionals (c.addToCerts || !isNull c.certMainHost) c.hosts) group) + ) + ); + in attrsets.mapAttrs (k: g: + if (!isNull (groupToDomain g)) + then config.services.websitesCerts // { + domain = groupToDomain g; + extraDomains = builtins.listToAttrs ( + map (d: attrsets.nameValuePair d null) (extraDomains g)); + } + else { + extraDomains = builtins.listToAttrs ( + map (d: attrsets.nameValuePair d null) (extraDomains g)); + } + ) groupedCerts; }