Score:0

Nginx try_files fails on first parameter and returns 404

jp flag

Bear with me, this is a long one.

In the beginning I created a Nginx server to server static files for my company, and it worked great with the following config snippet for serving the files:

server {
  # bunch of ssl stuff
  root /path/to/files;

  location / {
    include cors_support;
    sendfile on;
    sendfile_max_chunk 1m;

    try_files $uri =404;
  }

Simple, clean and functional. Until I thought I would add another function to this server: storing our application builds and serving them to our QA team. Since the application files can be quite big, I added another storage volume just for the builds and thought I could get away with this with a simple change to the Nginx config as follows (only relevant portions shown):

server {
  # mostly the same
  root /new/path/to/builds;

  location / {
    #same as before
    try_files $uri @cdn_files;
  }

  location @cdn_files {
    #some cors and send_file settings
    root /path/to/files;
    try_files $uri =404;
  }
}

What I expected to happen according to documentation:

  • request comes in for a file
  • checks the first block for the file
  • file found? yes=sends file no=redirect to named location
  • named location -> file found? yes=sends file no=404 page

What actually happens:

  • request comes in for a file
  • checks the first block for the file
  • file found? yes=sends file no=404 page

I have tried several different attempts at fixing this, including some insane "hail mary" attempts.

This produces the same result (404 page):

# ... irrelevant code
root /;
location / {
  # ... more irrelevant code
  try_files /new/path/to/builds/$uri /path/to/files/$uri =404;
}

This produces the same result (404 page):

# ...
root /new/path/to/builds;

location / {
  # ...
  try_files $uri @cdn_files;
}

location @cdn_files {
  # ...
  root /path/to/files;
  try_files $uri =403; #note that the page delivered is 404 and NOT 403
}

This produces a 404 as well:

# I removed the "root" directive from the server block for this test

location / {
  # ...
  root /new/path/to/builds;
  try_files $uri ../realitve/path/to/files/$uri =404;
}

A couple of other things to note:

  • The error logs only show 1 attempt at locating the file at the first parameter of the try_files directive.
  • If the file exists in the first parameter of the try_files directive the file is delivered
  • I don't think its relative but just in case: OS is Ubuntu 16.04

Edit:

  • Nginx version 1.21.0
Ivan Shatsky avatar
gr flag
I suppose you understand that the file will be searched at `root` + `uri`, that is, the `/uploads/myfile` request URI will be searched as `/new/path/to/builds/uploads/myfile` first and `/path/to/files/uploads/myfile` second. Besides that, there are no errors in your configuration. The only reason I can guess is that your request actually gets handled by some other location than the `location / { ... }` one. However to be sure the whole configuration needed, as well as the actual request URI.
Score:0
jp flag

So I finally managed to get this working by routing my incoming requests for the builds through a new URL and thus into their own server block, leaving the original file access as it was prior to modifications and both URL's now work to retrieve files from their specific locations.

I looked and googled and fiddled for several hours but I was never able to fix accessing files from multiple directories in a single server block, although from looking at the documentation it should have been possible.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.