How to Properly Configure Nginx proxy_pass for Subfolder Routing to Different Ports


3 views

Many developers encounter issues when trying to route subfolder requests to different ports using Nginx's proxy_pass. The configuration seems straightforward, but there are subtle details that can trip you up. Let's examine why the initial approach fails and how to fix it.

The main issue with the original config is that it doesn't properly handle the URI path when proxying. When you use:

location ^~ /app2 {
    proxy_pass http://aaa.bbb.ccc.ddd:8001;
}

Nginx sends the request to the upstream server with the /app2 prefix still included, which the backend server likely doesn't expect.

There are two proper ways to handle this:

Method 1: Strip the Prefix

location ^~ /app2/ {
    proxy_pass http://aaa.bbb.ccc.ddd:8001/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Notice the trailing slashes - they're crucial. The trailing slash after 8001/ tells Nginx to strip the /app2 prefix from the request.

Method 2: Rewrite the URL

location ^~ /app2 {
    rewrite ^/app2(.*)$ $1 break;
    proxy_pass http://aaa.bbb.ccc.ddd:8001;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

If your application uses WebSockets, you'll need additional headers:

location /app2/ {
    proxy_pass http://localhost:8001/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}

Watch out for these common mistakes:

  • Missing trailing slashes in either the location or proxy_pass
  • Not including necessary headers like Host
  • Forgetting that cookie paths might need adjustment
  • Not handling static assets properly if your app serves them

Here's a production-ready configuration:

server {
    listen 80;
    server_name example.com;
    
    location /app1/ {
        proxy_pass http://localhost:8000/;
        include proxy_params;
    }
    
    location /app2/ {
        proxy_pass http://localhost:8001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # Static files for app2
    location /app2/static/ {
        alias /path/to/app2/static/;
        expires 30d;
    }
}

Always test your changes with:

sudo nginx -t
sudo systemctl reload nginx

Then verify the routing works as expected by checking both the browser and Nginx access logs.


Many developers encounter issues when trying to route subfolders to different ports using Nginx's proxy_pass directive. The configuration seems straightforward, but subtle details can make it fail unexpectedly.

When you want to route example.com/app2 to localhost:8001, the naive approach would be:

location /app2 {
    proxy_pass http://localhost:8001;
}

However, this often doesn't work as expected because Nginx passes the complete URI path to the upstream server by default.

Here's the proper way to handle subfolder routing with proxy_pass:

server {
    listen 80;
    server_name example.com;

    location ^~ /app2/ {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # Note the trailing slash - critical for proper routing
        proxy_pass http://127.0.0.1:8001/;
    }
}

1. Trailing Slash Importance: The trailing slash in both location and proxy_pass tells Nginx to replace the matched path segment

2. Absolute Paths: Using 127.0.0.1 instead of localhost can prevent DNS resolution issues

3. Header Forwarding: The X-Forwarded-* headers ensure the backend server receives original client information

If you want the backend application to receive the original URI path:

location /app2 {
    rewrite ^/app2(.*)$ $1 break;
    proxy_pass http://127.0.0.1:8001;
}

Always test your Nginx configuration changes before applying them:

sudo nginx -t
sudo systemctl reload nginx

1. Check Nginx error logs: tail -f /var/log/nginx/error.log

2. Verify the upstream server is running and accessible

3. Use curl to test the routing: curl -v http://example.com/app2