Nginx – Howto rewrite URLs with two nginx as reverse proxies to gunicorn/Django

djangogunicornnginxreverse-proxyrewrite

I have a Django application, deployed with gunicorn on port 8000, on a VM with a backend nginx, port 80, on the same VM. The nginx config is:

    location / {
            proxy_http_version 1.1;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_pass http://localhost:8000/;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header REMOTE_USER $remote_user;
    }

    location /static/ {
    }

On the frontend side, there is another nginx, port 443, translating the user visible URLs https://myserver.com/myapplication/ into the internal http://myvm/. The nginx config is:

    location /myapplication/ {
            proxy_http_version 1.1;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_pass http://myvm/;
            proxy_redirect off;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header REMOTE_USER $remote_user;
    }

While I can access any URL such as https://myserver.com/myapplication/ without problems, the links in the Django application are all missing the /myapplication/ path component. What's wrong with my nginx setups? Is it the fronted or the backend that is wrong?

Best Answer

The frontend configuration is OK, but the backend needed a change:

    location / {
            ...
            proxy_set_header SCRIPT_NAME /myapplication;
    }

    location /myapplication/static/ {
            alias /path/to/myapplication/static/;
    }

The relevant bit was setting SCRIPT_NAME which seems to be interpreted by Django.

It would still be nice to have a solution, where the backend does not need to be configured with the path, maybe by passing the script name from the frontend to the backend and having some magic for the static files. But hey, it works!