summary refs log tree commit diff
path: root/fleet/modules/acme.nix
diff options
context:
space:
mode:
Diffstat (limited to 'fleet/modules/acme.nix')
-rw-r--r--fleet/modules/acme.nix55
1 files changed, 55 insertions, 0 deletions
diff --git a/fleet/modules/acme.nix b/fleet/modules/acme.nix
new file mode 100644
index 0000000..f06ac4e
--- /dev/null
+++ b/fleet/modules/acme.nix
@@ -0,0 +1,55 @@
+# SPDX-FileCopyrightText: V <v@unfathomable.blue>
+# SPDX-License-Identifier: OSL-3.0
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  webroot = "/var/lib/acme/challenges";
+in {
+  options = {
+    # We want to set webroot on every single certificate, but trying
+    # to do this by using genAttrs on the certificate attribute names
+    # produces infinite recursion. To get around this, we're instead
+    # setting webroot from within the certificate submodule itself.
+    #
+    # The fact that this is even possible is because submodules are
+    # just like normal modules, insofar that they can have both an
+    # 'options' and a 'config' attribute, both of which are scoped
+    # to the submodule itself. Additionally, normal merging logic
+    # is applied to module options, meaning we can just define the
+    # certificates option again and that'll be handled correctly.
+    #
+    # TODO(V): Add a global security.acme.webroot option to the upstream module
+    security.acme.certs = mkOption {
+      type = types.attrsOf (types.submodule {
+        inherit webroot;
+      });
+    };
+  };
+
+  config = {
+    security.acme = {
+      acceptTerms = true;
+      email = "acme@unfathomable.blue";
+    };
+
+    services.caddy.config = ''
+      ${concatStringsSep ", " (unique (mapAttrsToList (_: cert: "http://${cert.domain}") config.security.acme.certs))} {
+        import all
+
+        route {
+          # TODO(V): make use of the 'file' matcher, so this is guaranteed to never 404?
+          file_server /.well-known/acme-challenge/* {
+            root ${webroot}
+          }
+
+          # Manually handling http:// disables Caddy's automatic HTTPS
+          # redirects for the domain, so let's do that ourselves
+          redir https://{host}{uri} 308
+        }
+      }
+    '';
+  };
+}