{ lib, config, ... }: with lib; let cfg = config.services.danilafe-blog; sslForDomain = domain: (cfg.ssl == true) || (cfg.ssl."${domain}" or false); anySsl = any (mapAttrsToList (domain: pkg: sslForDomain domain) cfg.domains); virtualHost = domain: package: mkMerge [ { services.nginx.virtualHosts."${domain}" = mkMerge [ { root = package; } (mkIf (sslForDomain domain) { addSSL = true; enableACME = true; acmeRoot = cfg.challengePath; }) ]; } (mkIf (sslForDomain domain) { # Workaround for new configuration setting all of /var to be readonly. # See https://github.com/NixOS/nixpkgs/issues/139310 systemd.services."acme-${cfg.domain}".serviceConfig = { ReadWritePaths = [ cfg.challengePath ]; }; }) ]; virtualHosts = mapAttrsToList virtualHost cfg.domains; in { options.services.danilafe-blog = { enable = mkEnableOption "Daniel's blog service"; ssl = mkOption { type = types.either types.bool (types.attrsOf types.bool); default = false; description = "Enable SSL and ACME for all or some domains."; }; domains = mkOption { type = types.attrsOf types.package; description = "Attribute set where keys are domains and values are packages to host there."; }; challengePath = mkOption { type = types.str; description = "The location for ACME challenges"; }; }; config = mkIf cfg.enable (mkMerge (virtualHosts ++ [ { # Always enable nginx. services.nginx.enable = true; services.nginx.recommendedGzipSettings = true; } (mkIf anySsl { # If any domain uses SSL, enable ACME and accept terms. security.acme.email = "danila.fedorin@gmail.com"; security.acme.acceptTerms = true; }) ])); }