Christopher Armstrong
Christopher Armstrong

Reputation: 7953

'conflicting server name' with two default/catchall locations for nginx - one with default_server, one without?

I'm at my wit's end here. I've been fighting an nginx configuration for hours. Here are the two blocks I'm trying to use:

server {
    listen 80 default_server;
    location /health-check {
        default_type 'text/plain';
        access_log off;
        return 200;
    }
}

server {
    listen 80;
    location / {
        return 301 https://$http_host$request_uri;
    }
}

# other application servers/upstreams follow -- one is provided here for completeness,
# although the issue is almost certainly above

upstream quinoa-icehouse {
    server 172.17.8.100:49153;

}

server {
    server_name ~^quinoa-icehouse\.(?<domain>.+)$;
    server_name_in_redirect off;
    port_in_redirect off;


    listen 443 ssl spdy;
    listen 80;
    ssl_certificate /etc/ssl/deis.cert;
    ssl_certificate_key /etc/ssl/deis.key;

    location / {

        proxy_buffering             off;
        proxy_set_header            Host $host;

        proxy_set_header            X-Forwarded-Proto $scheme;

        proxy_set_header            X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_redirect              off;
        proxy_connect_timeout       30s;
        proxy_send_timeout          1200s;
        proxy_read_timeout          1200s;
        proxy_http_version          1.1;
        proxy_set_header            Upgrade           $http_upgrade;
        proxy_set_header            Connection        $connection_upgrade;

        proxy_next_upstream         error timeout http_502 http_503 http_504;

        add_header                  X-Deis-Upstream   $upstream_addr;

        proxy_pass                  http://quinoa-icehouse;
    }
}

Note that I want the /health-check endpoint to work only when other server names aren't matched, but I want the 301 to occur whenever a server name is matched.

I seem to have tried every combination of these directives, only to get:

[INFO] - 2014/12/30 01:26:34 [warn] 39#0: conflicting server name "" on 0.0.0.0:80, ignored

Is there a way for me to accomplish what I seek? Thank you!!

Upvotes: 0

Views: 1463

Answers (1)

Dayo
Dayo

Reputation: 12785

Essentially, you are going outside the Nginx' defined parameters. You cannot have two default server blocks sitting on each other so to speak.

You can however achieve what you need by defining:

  1. A catch all block listening on Port 80 to redirect all requests to Port 443
  2. A catch all block listening on Port 443 for all unmatched domains

You then need to ensure the following:

  1. Drop the "default_server" directive and rely on the position of the server blocks as in the example answer
  2. Ensure other application servers/upstreams only listen on Port 443.

So your config should be something along these lines:

http {

    [ ... ]

    # Default to redirect from Port 80 to Port 443
    server {
        listen 80;
        return 301 https://$host$request_uri;
    }
    # Default for unmatched domains on Port 443
    server {
        listen 443 ssl spdy;
        ssl_certificate /etc/ssl/someCert.cert;
        ssl_certificate_key /etc/ssl/someKey.key;
        # Return 403, 404 or 444
        return 403;
    }

    # Other servers.
    # 1. These must be below this for this configuration to work.
    # 2. None should listen on Port 80
    server {
        server_name ABC
        listen 443 ssl spdy;
        ssl_certificate /etc/ssl/someCert.cert;
        ssl_certificate_key /etc/ssl/someKey.key;

        [ ... ]

    }
    server {
        server_name XYZ
        listen 443 ssl spdy;
        ssl_certificate /etc/ssl/someCert.cert;
        ssl_certificate_key /etc/ssl/someKey.key;

        [ ... ]

    }
}

Refer to: Why is nginx responding to any domain name?

Note also that for simple server blocks that will just return simple responses, you don't need to have location blocks.

Upvotes: 2

Related Questions