Nginx is capable of more than serving web pages. It can load balance, cache and act as a reverse proxy.

We recently had need to access two web services on the same server through a single interface. This is where the reverse proxy came in.

  • Service A runs on port 9010
  • Service B runs on port 9020
  • Access to both services needs to be via a single front end using traditional http over port 80

Not ideal, but it’s not my system design, just a challenge we need to face. The way we tackled it was using an Nginx reverse proxy and split the calls to specific URL paths on each web service to the relevant underlying back end service.

Actually making Nginx act as a proxy is no more difficult than serving a web page. A quick modification in the /etc/nginx/default.conf file can easily identify a location and direct it as necessary.

server {
    listen       80;
    server_name  server.domain.tld;

   location ~ ^/(path1|path2|path3)(.*) {
       proxy_redirect /;

    location ~ ^/(path4|path5)(.*) {
       allow X.X.X.X;
       deny all;
       proxy_redirect /;

The important parts in this config snippet are:

location ~ ^/(path1|path2|path3)(.*) {

Use a regular expression to split the URL where the url path begins with path1, path2 or path3, pass it to a backend server specified as proxy_pass$1$2; and pass it the regex groups $1 (the path) and $2 (everything after the path).

Then when the backed server returns anything that may redirect to the client to use the configure URL directly, replace the in the redirect with just a / so the redirection comes back to the proxy and not try to use the direct URL.

So now anything going to http://server.domain.tld/path1…3 will be proxied to…3

Similarly the next location block causes anything going to http://server.domain.tld/path4…5 to be proxied to…5, but will only be allowed from the IP address X.X.X.X and denied from anywhere else.

Obviously the two services are so completely different that the paths are not the same on both services. eg. you can’t have path1 on service A and path1 on service B, but in this instance they are so different as to make this possible.

The client browser is now able to browse using simple http and no port like :9010, :9020 specified that could tangle them up.

A more realistic example may be to view 9010 as a web content server and 9020 as an api service. So more like

location ~ ^/(js|css|image)(.*) {


location ~ ^/(api)(.*) {

Then using a simple call to one front end I can call the paths for content and api and get the results seemingly from one URL.