When setting up an Nginx reverse proxy with multiple backend services, a common challenge arises: the subdirectory path gets passed through to the backend servers. For example, accessing https://example.com/site1
currently proxies to http://localhost:8081/site1
instead of the desired http://localhost:8081/
.
Here's the current problematic configuration:
location /site1 {
proxy_pass http://localhost:8081;
# Other proxy settings...
}
This setup preserves the /site1
prefix when forwarding requests to the backend service.
To remove the subdirectory prefix, we need to modify the proxy configuration in two ways:
location /site1/ {
proxy_pass http://localhost:8081/;
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_redirect http:// https://;
}
Key differences from the original:
- Added trailing slash to location block (
/site1/
) - Added trailing slash to proxy_pass URL (
http://localhost:8081/
)
When your backend performs redirects (like Rails' redirect_to
), we need to ensure they maintain the original subdirectory structure for external clients:
location /site1/ {
proxy_pass http://localhost:8081/;
proxy_redirect http://localhost:8081/ /site1/;
proxy_redirect https://localhost:8081/ /site1/;
# Other proxy settings...
}
Here's a full working example for both sites:
server {
listen 443;
server_name mysitename.com;
ssl on;
ssl_certificate ssl/mysitename.com.crt;
ssl_certificate_key ssl/mysitename.com.key;
keepalive_timeout 60;
location /site1/ {
proxy_pass http://localhost:8081/;
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_redirect http://localhost:8081/ /site1/;
proxy_redirect https://localhost:8081/ /site1/;
}
location /site2/ {
proxy_pass http://localhost:8082/;
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_redirect http://localhost:8082/ /site2/;
proxy_redirect https://localhost:8082/ /site2/;
}
# Redirect from /site1 to /site1/ (with trailing slash)
location = /site1 {
return 301 /site1/;
}
location = /site2 {
return 301 /site2/;
}
}
- Always include trailing slashes in both location and proxy_pass directives
- The
proxy_redirect
directives ensure backend redirects maintain the proper subdirectory - The separate
location =
blocks handle naked subdirectory redirects properly - Test your configuration thoroughly with
nginx -t
before reloading
If you encounter issues:
- Check Nginx error logs:
tail -f /var/log/nginx/error.log
- Verify backend receives proper requests: examine backend application logs
- Test with simple curl commands:
curl -v https://mysitename.com/site1
- Ensure all trailing slashes match in your configuration
When setting up a reverse proxy with NGINX, a common requirement is to remove the subdirectory prefix before passing the request to backend servers. In your case, accessing https://www.mysitename.com/site1
should proxy to http://localhost:8081/
without the /site1
prefix, but currently it's passing the full path.
The key is to use URL rewriting in the proxy_pass directive. Here's the corrected configuration:
server {
listen 443;
server_name mysitename.com;
ssl on;
ssl_certificate ssl/mysitename.com.crt;
ssl_certificate_key ssl/mysitename.com.key;
keepalive_timeout 60;
location /site1 {
proxy_pass http://localhost:8081/;
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_redirect http:// https://;
}
location /site2 {
proxy_pass http://localhost:8082/;
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_redirect http:// https://;
}
}
1. Added trailing slash (/
) to proxy_pass URLs
2. This tells NGINX to replace the matched prefix (/site1
) with /
3. Now /site1/login
becomes /login
on the backend
For applications that generate redirects (like Rails), you'll need additional configuration:
location /site1 {
proxy_pass http://localhost:8081/;
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_redirect http:// https://;
proxy_redirect ~^/(.*)$ /site1/$1;
}
For more complex scenarios, you can use regex locations:
location ~ ^/site1(/?)(.*) {
proxy_pass http://localhost:8081/$2$is_args$args;
# Other proxy settings...
}
Always test with:
nginx -t
systemctl reload nginx
Then verify with curl:
curl -v https://www.mysitename.com/site1/login