15

I would like to use the same upstream definition with multiple ports:

upstream production {
    server 10.240.0.26;
    server 10.240.0.27;
}
server {
    listen 80;
    server_name some.host;
    location / {
        proxy_pass http://production:1234;
    }
}
server {
    listen 80;
    server_name other.host;
    location / {
        proxy_pass http://production:4321;
    }
}

Using that configuration nginx -t throws: upstream "production" may not have port 1234 and returns with exitcode 1.

When I try to define the proxy_pass URL (or parts of) as a variable like:

set $upstream_url "http://production:1234"
set $upstream_host production;
set $upstream_port 1234;
proxy_pass $upstream_url;
# or
proxy_pass http://production:$upstream_port;
# or
proxy_pass http://$upstream:$upstream_port;

Nginx tries to resolve the name of my upstream via resolver:

 *16 no resolver defined to resolve production, client: ...., server: some.host, request: "GET / HTTP/1.1", host: "some.host"

For me, the proxy_pass doc sounds as if exactly that should not happen;

A server name, its port and the passed URI can also be specified using variables:

proxy_pass http://$host$uri; or even like this:

proxy_pass $request; In this case, the server name is searched among the described server groups, and, if not found, is determined using a resolver.

Tested with nginx versions:

  • 1.6
  • 1.9
  • 1.10
  • 1.11

Am I missing something? Is there a way to work around this?

2 Answers 2

23

You must define port in every server entry in upstream. If you don't nginx will set it to 80. So server 10.240.0.26; actually means server 10.240.0.26:80;.

You could define several upstream blocks though:

upstream production_1234 {
    server 10.240.0.26:1234;
    server 10.240.0.27:1234;
}
upstream production_4321 {
    server 10.240.0.26:4321;
    server 10.240.0.27:4321;
}
server {
    listen 80;
    server_name some.host;
    location / {
        proxy_pass http://production_1234;
    }
}
server {
    listen 80;
    server_name other.host;
    location / {
        proxy_pass http://production_4321;
    }
}

Another option is to configure your local DNS to resolve hostname production to several IPs, and in this case nginx will use them all.

http://nginx.org/r/proxy_pass: If a domain name resolves to several addresses, all of them will be used in a round-robin fashion.

server {
    listen 80;
    server_name some.host;
    location / {
        proxy_pass http://production:1234;
    }
}
1
  • Thanks for your answer! I did knew about using multiple upstream blocks but as I need to auto generate those (dynamically changing list of hosts and lots of ports) I thought I could probably just use one. Accepting anyways as your answer is correct and very complete
    – jayme
    Dec 30, 2016 at 8:28
4

When you use upstreams, the ports are defined in the upstream blocks:

upstream production {
    server 10.240.0.26:8080;
    server 10.240.0.27:8081;
}

In other words, nginx resolves proxy_pass argument either to a upstream group or a host:port pair. When you use a variable as argument, it only resolves to host:port pair.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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