diff --git a/flake.nix b/flake.nix index 36e5f61..3c5c3cb 100644 --- a/flake.nix +++ b/flake.nix @@ -34,5 +34,7 @@ }; defaultPackage = blog.english; } - ); + ) // { + nixosModule = (import ./module.nix); + }; } diff --git a/module.nix b/module.nix new file mode 100644 index 0000000..1c418a1 --- /dev/null +++ b/module.nix @@ -0,0 +1,60 @@ +{ 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; + }) + ])); + }