Skip to content

Nginx: use different backend based on HTTP header

Some load balancers have the ability to select different virtual server pools based on client http headers. This can be really convenient for staging and development work since you can use the same url across all instances. I wanted to do this on Nginx but had problems finding anyone that had done it before.

To accomplish this in Nginx you can use the following code in your configuration.

upstream apache {
     server 127.0.0.1:8080;
}

upstream staging {
     server 127.0.0.1:8081;
}

upstream development {
     server 127.0.0.1:8082;
}

# map to different upstream backends based on header
map $http_x_server_select $pool {
     default "apache";
     staging "staging";
     dev "development";
}

server {
     listen 80;
     server_name example.com;
     location / {
          proxy_pass http://$pool;

          #standard proxy settings
          proxy_set_header X-Real-IP $remote_addr;
          proxy_redirect off;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header X-NginX-Proxy true;
          proxy_connect_timeout 600;
          proxy_send_timeout 600;
          proxy_read_timeout 600;
          send_timeout 600;
     }
}

For example, if you set the “X-Server-Select” header in your browser to “staging” you get the staging server. You may want to create a visual identifier on the page to tell you what upstream server you are connecting to. Some useful plugins for setting client HTTP headers in the browser are:

Google Chrome: ModHeader
FireFox: Modify Headers

Published inWork

7 Comments

  1. Andrew Lovell

    Brilliant! Exactly the bit of code I needed to solve an urgent issue… Thanks

  2. Mohammad Jaqmaqji

    Hello Jason Heffner,
    I would like to say thak you a lot for this solution.. It is really what I was looking for. 🙂 (Y)

    what I mapped instead of custom header is $server_port in order to select upstream based on server port.

  3. KrustyHack

    Ay,

    Thanks for the example, that’s what I was looking for ! 🙂

    P.S : there is a missing “}” for location.

Leave a Reply

Your email address will not be published. Required fields are marked *