NGINX – Proxy_Pass Rewrite of Response Header Location

httphttp-headersnginxreverse-proxy

The aim of this nginx instance is to get GitLab and OpenWRT Luci to redirect through a reverse proxy. It's already working for several other websites, all which have a base url which seems to counter this issue.

  • GitLab in this example is on the local server at port 9000.
  • The nginx website is on port 8080.
  • OpenWRT has the exact same issue, but with /cgi-bin/luci/

The relevant nginx config for the example location is;

location /gitlab/ {
    proxy_pass http://127.0.0.1:9000/;
    proxy_redirect default;
}
  • Note that the results are the same with and without a trailing slash.

There are some header proxy configuration options being applied to this location.

# Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

# Basic Proxy Config
proxy_set_header    Host $host:$server_port;
proxy_set_header    Origin $scheme://$host:$server_port;    
proxy_set_header    Connection $http_connection;
proxy_set_header    Cookie $http_cookie;
proxy_set_header    Upgrade $http_upgrade;
proxy_set_header    X-Forwarded-Protocol $scheme;
proxy_set_header    X-Scheme $scheme;
proxy_set_header    X-Real-IP $remote_addr;
proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header    X-Forwarded-Ssl on;
proxy_set_header    X-Frame-Options SAMEORIGIN;

# Advanced Proxy Config
send_timeout            5m;
proxy_read_timeout      300;
proxy_send_timeout      300;
proxy_connect_timeout   300;

proxy_buffers 32 4k;
proxy_buffer_size           4k;
proxy_busy_buffers_size     64k;
proxy_temp_file_write_size  64k;

proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;]
  • Commenting out #proxy_set_header Host instead redirects the browser to https://127.0.0.1:9000/users/sign_in

When browsing to https://website.com:8080/gitlab/;

GET /gitlab/ HTTP/1.1
Host: website.com:8080

The response incorrectly goes back to /users/sign_in instead of /gitlab/users/sign_in

HTTP/1.1 302 Found
Cache-Control: no-cache
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Location: https://website.com:8080/users/sign_in

Browsing manually to https://website:8080/gitlab/users/sign_in loads the page, but no assets as they fall until the same issue as above.

GitLab Asset Fail

Reading nginx docs, it suggests that the default proxy behaviour should handle this scenario, though it seems to fail.

The logs don't seem to show much.

What additional steps should be taken to help diagnose why this might be happening?

Best Answer

Add a trailing slash to your proxy_pass target.

Update : The OP didn't precise the vhost was accepting https. As the scheme is forwarded to the backend server with additionnal headers, then an issue occurs since proxy_redirect default; orders nginx to expect http scheme by default when rewriting Location headers in upstream replies, instead of https.

So, this had to be changed explicitely to a more generic form (the trailing slash is still necessary) :

location /gitlab/ {
    proxy_pass http://127.0.0.1:9000/;
    proxy_redirect $scheme://$host:$server_port/ /gitlab/;
}