{ lib, config, ... }: with lib; let cfg = config.services.danilafe-blog; sslForDomain = domain: package: package.ssl; anySsl = any id (mapAttrsToList sslForDomain cfg.domains); virtualHost = domain: package: { virtualHosts."${domain}" = mkMerge [ { root = package; } (mkIf (sslForDomain domain package) { addSSL = true; enableACME = true; acmeRoot = cfg.challengePath; }) ]; }; service = domain: package: { # Workaround for new configuration setting all of /var to be readonly. # See https://github.com/NixOS/nixpkgs/issues/139310 "acme-${domain}".serviceConfig = { ReadWritePaths = [ cfg.challengePath ]; }; }; virtualHosts = mapAttrsToList virtualHost cfg.domains; services = mapAttrsToList service (filterAttrs sslForDomain cfg.domains); in { options.services.danilafe-blog = { enable = mkEnableOption "Daniel's blog service"; domains = mkOption { type = types.attrsOf types.package; default = {}; 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.services.nginx = mkIf cfg.enable (mkMerge (virtualHosts ++ [ { # Always enable nginx. enable = true; recommendedGzipSettings = true; } ])); config.systemd.services = mkIf cfg.enable (mkMerge services); config.security.acme = mkIf (cfg.enable && anySsl) { # If any domain uses SSL, enable ACME and accept terms. email = "danila.fedorin@gmail.com"; acceptTerms = true; }; }