]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - modules/websites/default.nix
Add certificate creation and handling to websites
[perso/Immae/Config/Nix.git] / modules / websites / default.nix
index 6a18c8afb1829f153ea852ee225f67dac9f1fb7a..b76aeead489cea4b2810c9f2537637489c835506 100644 (file)
@@ -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,6 +75,16 @@ 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 = []; };
@@ -145,4 +158,42 @@ in
         ++ [ (redirectVhost icfg.ips) ];
     })
   ) 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;
 }