# Nginx servers on both \*:80 and \<ip\>:80? also duplicate listen parameters error when binding by just

**URL:** <https://www.ruby-forum.com/t/nginx-servers-on-both-80-and-ip-80-also-duplicate-listen-parameters-error-when-binding-by-just/244388>\
**Category:** NGINX\
**Created:** [March 31, 2016, 7:21pm UTC](https://www.ruby-forum.com/t/nginx-servers-on-both-80-and-ip-80-also-duplicate-listen-parameters-error-when-binding-by-just/244388 "2016-03-31T19:21:42Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sadaf\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@Sadaf\_N](https://www.ruby-forum.com/u/Sadaf_N)\
**Post date:** [March 31, 2016, 7:21pm UTC](https://www.ruby-forum.com/t/nginx-servers-on-both-80-and-ip-80-also-duplicate-listen-parameters-error-when-binding-by-just/244388/1 "2016-03-31T19:21:42Z")

</div>

I would like to have an Nginx setup where I have specific logic  
depending  
on which interface (ip) the request arrived on.

I was able to make this work by having a server stanza for each ip on  
the  
server, but was’t able to do a combination of a specific ip and a  
wildcard  
ip (as a catchall) - is there a way to do that with some option  
combination  
(i.e. nginx listens on \*:80, but matches the server stanza by ip?)

The scenario I’m playing towards is that I have a dedicated connection  
to a  
CDN and I want to pass thru certain headers if they arrive via the  
dedicated interface, strip them if they arrive on other interface.

When I did the server{} per IP approach nginx complained about duplicate  
listen settings for the second IP even though both server stanzas were  
bound to a specific port/interface. Is this a bug per chance?

This was with Nginx 1.9.0 btw, perhaps newer versions have a different  
behavior?

---

<div class="post-metadata">

**Author:** ![CJ\_Ess](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c68b51/32.png) [@CJ\_Ess](https://www.ruby-forum.com/u/CJ_Ess)\
**Post date:** [March 31, 2016, 10:29pm UTC](https://www.ruby-forum.com/t/nginx-servers-on-both-80-and-ip-80-also-duplicate-listen-parameters-error-when-binding-by-just/244388/2 "2016-03-31T22:29:49Z")

</div>

On Thu, Mar 31, 2016 at 01:21:02PM -0400, CJ Ess wrote:

Hi there,

> I would like to have an Nginx setup where I have specific logic depending  
> on which interface (ip) the request arrived on.

multiple server{} with different “listen”; possibly with an “include  
common-config” entry.

Note: “listen” is on an ip, not an interface.

> I was able to make this work by having a server stanza for each ip on the  
> server, but was’t able to do a combination of a specific ip and a wildcard  
> ip (as a catchall) - is there a way to do that with some option combination  
> (i.e. nginx listens on \*:80, but matches the server stanza by ip?)

I don’t understand what you are describing. Could you try again, perhaps  
with a config example?

When I use

# === server { listen 127.0.0.1:8088; return 200 “listen 127.0.0.1:8088\n”; } server { listen 10.0.1.2:8088; return 200 “listen 10.0.1.2:8088\n”; } server { listen 8088; return 200 “listen 8088\n”; }

I get the following output, which is what I expect:

$ curl [http://127.0.0.1:8088/](http://127.0.0.1:8088/)  
listen 127.0.0.1:8088  
$ curl [http://127.0.0.2:8088/](http://127.0.0.2:8088/)  
listen 8088

> The scenario I’m playing towards is that I have a dedicated connection to a  
> CDN and I want to pass thru certain headers if they arrive via the  
> dedicated interface, strip them if they arrive on other interface.

As above, if “interface” is replaced with “ip”, this can work with two  
server{} blocks.

> When I did the server{} per IP approach nginx complained about duplicate  
> listen settings for the second IP even though both server stanzas were  
> bound to a specific port/interface. Is this a bug per chance?

What short server{} config can I use to reproduce the complaint?

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![CJ\_Ess](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c68b51/32.png) [@CJ\_Ess](https://www.ruby-forum.com/u/CJ_Ess)\
**Post date:** [April 2, 2016, 10:36pm UTC](https://www.ruby-forum.com/t/nginx-servers-on-both-80-and-ip-80-also-duplicate-listen-parameters-error-when-binding-by-just/244388/3 "2016-04-02T22:36:44Z")

</div>

Your right, I should make a simple test case like you did in the prev  
message. I’ll put that together.

---

<div class="post-metadata">

**Author:** ![CJ\_Ess](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c68b51/32.png) [@CJ\_Ess](https://www.ruby-forum.com/u/CJ_Ess)\
**Post date:** [April 29, 2016, 11:13pm UTC](https://www.ruby-forum.com/t/nginx-servers-on-both-80-and-ip-80-also-duplicate-listen-parameters-error-when-binding-by-just/244388/4 "2016-04-29T23:13:15Z")

</div>

Francis,

Sorry it took so long, I’ve finally come back to this question.

The example you gave works great:

```
server {
    listen 127.0.0.1:8088;
    return 200 "listen 127.0.0.1:8088\n";
}
server {
    listen 10.0.1.2:8088;
    return 200 "listen 10.0.1.2:8088\n";
}
server {
    listen 8088;
    return 200 "listen 8088\n";
}

```

Where I get into problem is if I do something like this:

```
server {
    listen 127.0.0.1:8088 backlog=65536 deferred;
    return 200 "listen 127.0.0.1:8088\n";
}
server {
    listen 10.0.1.2:8088 backlog=65536 deferred;
    return 200 "listen 10.0.1.2:8088\n";
}
server {
    listen 8088;
    return 200 "listen 8088\n";
}

```

In that case I get errors like “nginx: [emerg] bind() to 0.0.0.0:8088  
failed (98: Address already in use)”. So the workaround is obviously not  
to  
use those options - I could patch the source to use a backlog larger  
then  
511.

This example also works well:

server {  
listen \*:80;  
server\_name “test\_a”;  
return 200 “listen test\_a”;  
}

server {  
listen \*:80;  
server\_name “test\_b”;  
return 200 “listen test\_b”;  
}

server {  
listen \*:80 default\_server;  
return 200 “listen \*”;  
}

But if I change it to this:

server {  
listen \*:80 backlog=65536 deferred;  
server\_name “test\_a”;  
return 200 “listen test\_a”;  
}

server {  
listen \*:80 backlog=65536 deferred;  
server\_name “test\_b”;  
return 200 “listen test\_b”;  
}

server {  
listen \*:80 backlog=65536 deferred default\_server;  
return 200 “listen \*”;  
}

Then I get the error message “nginx: [emerg] duplicate listen options  
for  
0.0.0.0:80 in /etc/nginx/nginx.conf”. I can fix it by doing something  
like  
this:

server {  
listen \*:80;  
server\_name “test\_a”;  
return 200 “listen test\_a”;  
}

server {  
listen \*:80;  
server\_name “test\_b”;  
return 200 “listen test\_b”;  
}

server {  
listen \*:80 backlog=65536 deferred default\_server;  
return 200 “listen \*”;  
}

From the ss -l output I am picking up the larger listen queue which I’m  
happy about, though its confusing why nginx is picking them from that  
last  
server stanza (it has the same behavior without the default\_server  
keyword). If I’m doing a virtual hosting type setup and I’m including  
all  
of my server definitions from individual files in a subdirectory, it  
appears that any one of them could bump up the backlog, but if any two  
server stanzas have options to do it then it causes an error. Maybe the  
best way to do it is to have some sort of dummy entry that sets the  
options

- if its always the last server stanza that sets the listen options then  
maybe include all the other server stanzas and have the dummy at the  
end  
that sets the backlog and deferred options?

---

<div class="post-metadata">

**Author:** ![CJ\_Ess](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c68b51/32.png) [@CJ\_Ess](https://www.ruby-forum.com/u/CJ_Ess)\
**Post date:** [April 30, 2016, 10:27am UTC](https://www.ruby-forum.com/t/nginx-servers-on-both-80-and-ip-80-also-duplicate-listen-parameters-error-when-binding-by-just/244388/5 "2016-04-30T10:27:21Z")

</div>

On Fri, Apr 29, 2016 at 05:12:44PM -0400, CJ Ess wrote:

Hi there,

> ```
> server {
> listen 8088;
> return 200 "listen 8088\n";
> }
> 
> ```
> 
> In that case I get errors like “nginx: [emerg] bind() to 0.0.0.0:8088  
> failed (98: Address already in use)”. So the workaround is obviously not to  
> use those options - I could patch the source to use a backlog larger then  
> 511.

That is covered (not necessarily explicitly) at  
[Module ngx\_http\_core\_module](http://nginx.org/r/listen). There’s a section on “parameters specific to  
socket-related system calls”; and the description of “bind” indicates  
that it can be applied implicitly.

If your OS does not allow you to bind() to both IP:port and to  
INADDR\_ANY:8088, then the above config (which says to bind individually  
to  
127.0.0.1:8088 and 10.0.1.2:8088 and 0.0.0.0:8088) is broken on your OS.

> ```
> listen *:80 backlog=65536 deferred;
> listen *:80 backlog=65536 deferred;
> listen *:80 backlog=65536 deferred default_server;
> 
> ```

> Then I get the error message “nginx: [emerg] duplicate listen options for  
> 0.0.0.0:80 in /etc/nginx/nginx.conf”.

“…only once for a given address:port pair”.

> ```
> listen *:80;
> listen *:80;
> listen *:80 backlog=65536 deferred default_server;
> 
> ```

> From the ss -l output I am picking up the larger listen queue which I’m  
> happy about, though its confusing why nginx is picking them from that last  
> server stanza (it has the same behavior without the default\_server  
> keyword).

I think it’s clear why it happens, when you know what system calls are  
used in response to the config.

I’m not sure how the documentation could be enhanced for clarity without  
becoming unwieldy.

> If I’m doing a virtual hosting type setup and I’m including all  
> of my server definitions from individual files in a subdirectory, it  
> appears that any one of them could bump up the backlog, but if any two  
> server stanzas have options to do it then it causes an error.

There are lots of other things that could be put into the files that  
would be invalid configurations too.

> Maybe the  
> best way to do it is to have some sort of dummy entry that sets the options
> 
> - if its always the last server stanza that sets the listen options then  
> maybe include all the other server stanzas and have the dummy at the end  
> that sets the backlog and deferred options?

Once upon a time, only the default\_server entry could set them (but  
it wasn’t called default\_server then). Since that is a once-per-port  
option too, perhaps you could make a policy of only setting them in  
that server{}?

You’d still have the issue of multiple bind()s; but that is presumably  
“change your config design or change your OS”.

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
