0

When a user visits website.com I want the contents of the /home/user/project/frontend to be served (a single page app)

When a URL comes in that matches /assets, it should look into the /home/user/project/backend/staticfiles folder, which contains collected static files from django.

To the above effect, below is my Nginx conf

upstream backend {
    server 127.0.0.1:8000;
}

server {
    listen 80;

    server_name website.com www.website.com;
    root /home/user/project/frontend;
    index index.html index.htm;

    location /assets {
        root /home/user/project/backend/staticfiles;
    }

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~^/(admin|api|auth|swagger|webhook) {
      proxy_connect_timeout 600;
      proxy_send_timeout 600;
      proxy_read_timeout 600;
      send_timeout 600;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_pass http://backend;
    }
}

Intuitively, the above should work, right? However, when a request like website.com/assets/admin/css/base.css comes in, according to the logs, Nginx goes looking into the /home/user/project/frontend folder, which is NOT what the configuration is saying it should do.

2022/08/24 22:42:29 [error] 18946#18946: *1 open() "/home/user/project/frontend/assets/admin/css/base.css" failed (2: No such file or directory), client: xx.xx.xx.xx, server: xx.xx.xx.xx, request: "GET /assets/admin/css/base.css HTTP/1.1", host: "website.com"

On a different server, I have the EXACT same configuration, EXACT same django-react setup, EXACT nginx version, EXACT everything, yet, on this fresh installation, with the SAME configuration, Nginx is absolutely ignoring the location /assets { } block like it doesn't even exist.

Is there a typo or something somewhere? Because nginx -t also indicates the file is fine.

When I do website.com/assets/admin/css/base.css/ (note trailing forward slash), Nginx attempts THEN to look into the right folder, although it's off too.

2022/08/24 23:01:39 [error] 18946#18946: *4 "/home/user/project/backend/staticfiles/assets/admin/css/base.css/index.html" is not found (2: No such file or directory), client: xx.xx.xx.xx, server: xx.xx.xx.xx, request: "GET /assets/admin/css/base.css/ HTTP/1.1", host: "website.com"

Maybe the whole approach I'm using is buggy, unreliable and or inconsistent. Maybe there's a better approach (although as I type this, I have the EXACT same conf working as expected on another server).

Please enlighten me.

KhoPhi
  • 9,660
  • 17
  • 77
  • 128
  • Changing the log level to debug will likely allow you to self-answer, note that that root directive means nginx will look for the full url under the root I.e. http://example.com/assets/abc.xy -> `/home/user/project/backend/staticfiles/assets/abc.xyz` - is that the intent?`This question is better suited to serverfault.com btw. – AD7six Aug 24 '22 at 23:31
  • The intent is, `example.com/assets/abc.xy` should point to on file `/home/user/project/backend/staticfiles/abc.xy` – KhoPhi Aug 24 '22 at 23:36
  • Ok I find it hard to believe this works elsewhere as claimed then - if it is working, it’s not working in the way you think it is :). It’d be helpful to remove the hyperbole (blatantly, absolutely etc.) – AD7six Aug 24 '22 at 23:37
  • I see you’ve asked [similar questions in the past](https://stackoverflow.com/questions/70289641/nginx-alias-still-points-to-and-loads-from-root-directory). Note that [alias](https://nginx.org/en/docs/http/ngx_http_core_module.html#alias) and root are not analogous - I think we now know how you solved this before :). – AD7six Aug 25 '22 at 00:09
  • Yes @AD7six. I also find it hard to believe myself. However, the link you shared don't have the solution (my previous question). And at least from my new setup conf, what I thought was the "solution" is still broken (although working right NOW on the other conf) – KhoPhi Aug 25 '22 at 09:46

1 Answers1

0

Here's an updated conf file, that I can confirm to be working on my new setup.

From this article:

The modifier ^~ in the following location block results in a case sensitive regular expression match. Therefore the URI /images or /images/logo.png will be matched but stops searching as soon as a match is found.

upstream backend {
    server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name xx.xx.xx.xx;

    root /home/user/project/frontend;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ^~ /assets/ {
        root /home/user/project/backend;
    }

    location ~^/(admin|api|auth|swagger|webhook) {
        ...
    }
}

And so with the above, when Nginx gets a request like

example.com/assets/admin/base.css, it points to the folder

/home/user/project/backend/assets/admin/base.css

Basically, it appends the location block URL to the root path.

In my django settings.py, I have these

STATIC_URL = "/assets/"
STATIC_ROOT = os.path.join(BASE_DIR, "assets")
KhoPhi
  • 9,660
  • 17
  • 77
  • 128