# SPDX-FileCopyrightText: V # 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; defaults.email = "acme@unfathomable.blue"; }; services.caddy.extraConfig = '' ${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 } } ''; }; }