diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 2951e63e863e..100fabf902f8 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -15,6 +15,9 @@ let } // (optionalAttrs vhostConfig.enableACME { sslCertificate = "/var/lib/acme/${serverName}/fullchain.pem"; sslCertificateKey = "/var/lib/acme/${serverName}/key.pem"; + }) // (optionalAttrs (vhostConfig.useACMEHost != null) { + sslCertificate = "/var/lib/acme/${vhostConfig.useACMEHost}/fullchain.pem"; + sslCertificateKey = "/var/lib/acme/${vhostConfig.useACMEHost}/key.pem"; }) ) cfg.virtualHosts; enableIPv6 = config.networking.enableIPv6; @@ -174,7 +177,7 @@ let redirectListen = filter (x: !x.ssl) defaultListen; - acmeLocation = '' + acmeLocation = optionalString (vhost.enableACME || vhost.useACMEHost != null) '' location /.well-known/acme-challenge { ${optionalString (vhost.acmeFallbackHost != null) "try_files $uri @acme-fallback;"} root ${vhost.acmeRoot}; @@ -194,7 +197,7 @@ let ${concatMapStringsSep "\n" listenString redirectListen} server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases}; - ${optionalString vhost.enableACME acmeLocation} + ${acmeLocation} location / { return 301 https://$host$request_uri; } @@ -204,7 +207,7 @@ let server { ${concatMapStringsSep "\n" listenString hostListen} server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases}; - ${optionalString vhost.enableACME acmeLocation} + ${acmeLocation} ${optionalString (vhost.root != null) "root ${vhost.root};"} ${optionalString (vhost.globalRedirect != null) '' return 301 http${optionalString hasSSL "s"}://${vhost.globalRedirect}$request_uri; @@ -555,6 +558,14 @@ in are mutually exclusive. ''; } + + { + assertion = all (conf: !(conf.enableACME && conf.useACMEHost != null)) (attrValues virtualHosts); + message = '' + Options services.nginx.service.virtualHosts..enableACME and + services.nginx.virtualHosts..useACMEHost are mutually exclusive. + ''; + } ]; systemd.services.nginx = { @@ -580,7 +591,7 @@ in security.acme.certs = filterAttrs (n: v: v != {}) ( let vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts; - acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME) vhostsConfigs; + acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME && vhostConfig.useACMEHost == null) vhostsConfigs; acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = { user = cfg.user; group = lib.mkDefault cfg.group; diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix index 29f08cc4f307..bf18108a1a3c 100644 --- a/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -48,7 +48,21 @@ with lib; enableACME = mkOption { type = types.bool; default = false; - description = "Whether to ask Let's Encrypt to sign a certificate for this vhost."; + description = '' + Whether to ask Let's Encrypt to sign a certificate for this vhost. + Alternately, you can use an existing certificate through . + ''; + }; + + useACMEHost = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + A host of an existing Let's Encrypt certificate to use. + This is useful if you have many subdomains and want to avoid hitting the + rate limit. + Alternately, you can generate a certificate through . + ''; }; acmeRoot = mkOption {