When using Nginx's proxy_pass
to route subpaths to different backend services, the original path (/en
in this case) gets forwarded to the upstream server by default. This creates routing issues when the backend application expects requests at root level (/
).
Here are the most reliable approaches to solve this path prefix issue:
# Solution 1: Rewrite before proxy_pass
location /en/ {
rewrite ^/en/(.*) /$1 break;
proxy_pass http://luscious;
}
# Solution 2: Trailing slash in proxy_pass
location /en/ {
proxy_pass http://luscious/; # Note the trailing slash
}
# Solution 3: Using variables
location /en/ {
proxy_pass http://luscious$request_uri;
proxy_set_header X-Original-URI $request_uri;
}
For most use cases, Solution 2 provides the cleanest implementation:
upstream luscious_backend {
server backend.example.com:8000;
}
server {
listen 80;
server_name example.com;
location /en/ {
proxy_pass http://luscious_backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Optional: Remove /en prefix from other headers
proxy_redirect http://luscious_backend/ /en/;
}
}
- Forgetting the trailing slash in either location or proxy_pass
- Not handling static assets paths correctly
- Mixing rewrite rules with proxy_pass unnecessarily
- Ignoring header modifications needed for the backend
For more complex routing scenarios:
location ~ ^/(en|fr|de)(/.*)?$ {
set $lang $1;
set $path $2;
proxy_pass http://backend_servers/$path$is_args$args;
proxy_set_header X-Language $lang;
}
When implementing reverse proxy with Nginx, a common challenge arises when you need to "mount" an application under a specific path while the upstream server expects requests at its root path. Consider this scenario:
upstream luscious {
server lixxxx.members.linode.com:9001;
}
server {
root /var/www/example.com/current/public/;
server_name example.com;
location /en {
proxy_pass http://luscious;
}
}
Accessing example.com/en
results in a 404 error because the upstream server receives the request with the /en
path prefix, which doesn't exist on the backend application.
The most elegant solution is to modify the proxy_pass
directive to strip the /en
prefix before forwarding to the upstream server:
location /en {
proxy_pass http://luscious/;
}
Notice the trailing slash after the upstream name. This simple change tells Nginx to replace the matched /en
path with /
when forwarding the request.
For more complex scenarios where you need to preserve part of the path or perform pattern-based rewriting, you can use regular expressions:
location ~ ^/en(/.*)$ {
proxy_pass http://luscious$1;
}
This configuration will:
- Match any path starting with
/en
- Capture the remaining path in
$1
- Proxy to the upstream server with just the captured portion
Here's a production-ready configuration that includes common proxy settings:
upstream backend_app {
server backend.example.com:8080;
keepalive 32;
}
server {
listen 80;
server_name example.com;
location /en/ {
proxy_pass http://backend_app/;
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;
# Timeout settings
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
# Buffering settings
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 16k;
}
}
When implementing path rewriting with Nginx proxy_pass, watch out for these issues:
- Missing trailing slash:
proxy_pass http://backend
vsproxy_pass http://backend/
behave differently - Double slashes: Ensure your rewritten path doesn't create invalid URLs like
http://backend//path
- Header preservation: Always forward the Host header to prevent routing issues
To debug proxy issues, examine the request headers received by your upstream server or add these to your Nginx config:
location /en {
add_header X-Proxied-Path $request_uri;
proxy_pass http://luscious/;
}