Open nh2 opened 2 years ago
I believe that the fix should be something like this:
The definition of a extraDomainNames
should result in the rendering of an acmeLocation
block into nginx.conf
as defined here:
I use this NixOS config as a workaround instead, restricting the return 404
(that was before on the server
level) to be inside location /
:
{
services.nginx = {
enable = true;
virtualHosts = {
# Configure dummy default servers that return `404 Not Found`.
# Without this, an arbitrary vhost will be picked for answering requests
# that do not match any configured vhost (namely, the first one rendered into `nginx.conf`)!
# See:
# https://serverfault.com/questions/420351/best-way-to-prevent-default-server
# We must allow the `/.well-known/acme-challenge` to not break LetsEncrypt ACME `extraDomainNames`, see issue:
# acme/letsencrypt: Obtaining extraDomainNames certs fails if nginx default server is configured
# (https://github.com/NixOS/nixpkgs/issues/180980).
# The root is the default of `security.acme.certs.<name>.webroot`, see:
# * https://github.com/NixOS/nixpkgs/blob/09b76341b3eb1e3f72ebfc29c7fe04c20bdb92de/nixos/modules/security/acme/default.nix#L468
# * https://github.com/NixOS/nixpkgs/blob/71d7a4c037dc4f3e98d5c4a81b941933cf5bf675/nixos/modules/services/web-servers/nginx/default.nix#L280
"defaultDummy404" = {
default = true;
serverName = "_";
locations."/".extraConfig = "return 404;";
locations."/.well-known/acme-challenge".root = "/var/lib/acme/acme-challenge";
};
"defaultDummy404ssl" =
let
# A self-signed certificate, just to render "Not Found" messages.
snakeoilCert = pkgs.runCommand "nginx-snakeoil-cert" { buildInputs = [ pkgs.openssl ]; } ''
mkdir "$out"
openssl req -newkey rsa:4096 -x509 -sha256 -days 36500 -subj '/CN=Snakeoil CA' -nodes -out "$out/cert.pem" -keyout "$out/cert.key"
'';
in
# Note: Enabling this catch-all SSL dummy default_server breaks HTTPS clients without SNI, see
# https://trac.nginx.org/nginx/ticket/195#comment:11
# That's OK for us, as we require SNI anyway since we run multiple domains on the same IP.
# That's also why we use `proxy_ssl_server_name on;` for all `proxy_pass` settings.
{
default = true;
serverName = "_";
locations."/".extraConfig = "return 404;";
locations."/.well-known/acme-challenge".root = "/var/lib/acme/acme-challenge";
# Dummy SSL config
onlySSL = true;
sslCertificate = "${snakeoilCert}/cert.pem";
sslCertificateKey = "${snakeoilCert}/cert.key";
};
};
};
}
Hello. I've gotten some time to look into this. I'm really struggling to understand the problem + proposed solution, but I think the key thing here is that in your situation there is no vhost configured for one or all of the extraDomainNames that you expect to validate via HTTP-01? This feels like expected behaviour, or should I say that not specifying explicit vhosts for HTTP-01 solving has unintentionally worked.
Your workaround looks like the best solution regardless.
I believe that the NixOS ACME module is somehow incompatible with defining an nginx
default_server
block.My server uses this ACME config:
This works by itself and renews its certificate. But the following improvement I tried to make to my
nginx
config breaks it:In nginx, by default, the first
server {}
block configured will reply to requests for all domains, even those that you have not configured it to answer to. This is described in: https://serverfault.com/questions/420351/best-way-to-prevent-default-serverThis is often not desired, because it results in seemingly random pages to be loaded. Instead, most people want to see
HTTP 404
if a user accesses the server on a DNS domain that is not supposed to serve HTTP. For example, if I have the Matrix Synapse/Element chat server and UI enabled, going tomuc.nh2.me
in the browser will bring me to its UI, even though these two have nothing to do with each other!Thus, I tried to usethe following
default_server
config to return HTTP code 404 on HTTP/HTTPs.Unfortunately, that led to HTTP 404 being returned for the
extraDomainNames
validation requests!The LetsEncrypt error I got during NixOS system activation:
Expected behavior
Renewing
extraDomainNames
should work even with an nginx default server configured.Notify maintainers
CC @m1cr0man wo is knowledgeable in ACME