2

I serve a site from nginx that is available both with internal host names as well as external ones. I want to force external access to use https, but keep http for internal access (because I can't get certificates for those internal addresses).

The following configuration does what I want:

#redirect port 80 http to 443 https
server{
    listen 80 default_server;
    listen [::]:80 default_server;
    #just for external access
    server_name hostname.external_domain;
    return 301 https://$host$request_uri;
}

# serve both http and https internally
server {
    listen 80;
    listen 443 ssl;
    listen [::]:80;
    listen [::]:443 ssl;

    server_name hostname hostname.internal_domain hostname.external_domain;

...

but nginx -t gives me the warning

nginx: [warn] conflicting server name "hostname.external_domain" on 0.0.0.0:80, ignored

because this hostname is used in both server definitions. But it needs to be there, or else I either won't catch the http access attempt or the redirected one.

I know I could add a 3rd server definition with just port 443 and without port 80 for hostname.external_domain and remove just this name from the 2nd server and this would probably remove the warning, but that I'd had to copy the whole content of the server block too, which I find kind of redundant.

Is there a better solution?

1

Option 1.

Use three server blocks (as mentioned in your question) but offload the duplicated content into a separate file, using an include directive to pull it into each of the relevant server blocks. See this document for details.


Option 2.

The default_server does not need a server_name statement. However, you should swap the default_server to the other server block, so that the 1st server block becomes the more specific one.

For example:

server{
    listen 80;
    listen [::]:80;
    server_name hostname.external_domain;
    return 301 https://$host$request_uri;
}

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    listen [::]:80 default_server;
    listen [::]:443 ssl default_server;

    ...
}

The second server_block does not need to match using a server_name as it will match anything that the first server block does not explicitly match.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.