Properly setting up a "default" nginx server for https

Roar asked:

I have several servers running on the same machine, some with http only, some with both http and https. There are several server blocks defined in separate files which are included from the main config file.

I have set up a “default” server for http which will serve a generic “maintenance page” to requests that don’t match any of the other server_names in the other config files. The http default server works as expected, it uses the server_name “_” and it appears first in the list of includes (because I have observed that in the case of duplicate server_names across servers, the one appearing first is used). This works great.

I would expect the same exact server block (only switching “listen 80 default_server” to “listen 443 default_server” and also instead of serving page “return 444”) however it does not. Instead, it appears that the new default https server is actually grabbing all incoming https connections and causing them to fail, although the other server blocks have more appropriate server_names for the incoming requests. Removing the new default https server will cause semi-correct behavior to resume: the websites with https will all load correctly; but the websites without https will all be routed to the first https server in the include files (which according to the docs, if no “default_server” appears, then the first server block to appear will be “default”).

So my question is, what is the correct way to define a “default server” in nginx for ssl connections? Why is it that when I explicitly set a “default_server” it gets greedy and grabs all connections whereas when I implicitly let nginx decide the “default server” it works like I would expect (with the incorrect server set as default and the other real servers behaving correctly)?

Here are my “default servers”. Http works without breaking other servers. Https breaks other servers and consumes all.

server {
    listen 443 ssl default_server;
    server_name _;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    return 444;
}

server {
    listen *:80 default_server;
    server_name _;
    charset utf-8;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    root /home/path/to/templates;

    location / {
        return 503;
    }

    error_page 503 @maintenance;

    location @maintenance {
        rewrite ^(.*)$ /maintenance.html break;
    }
}

Any of you see what might be wrong here?

My answer:


If you want to be absolutely sure, then use separate IP addresses for hosts which should not answer on HTTPS and hosts which should. This also resolves the “invalid certificate” browser warning problem.


View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.