How to Use Nginx try_files Directive to Serve Files from Multiple Directory Trees


4 views

In complex web applications, we often need to serve static files from multiple directory structures while maintaining a clean URL pattern. Consider this directory layout:

images/siteA/foo.jpg
images/siteB/b/bar.jpg
images/siteC/example.jpg

We want URLs like http://example.com/images/foo.jpg to serve files from these distributed locations without exposing the actual directory structure to end users.

The naive implementation using simple try_files often leads to redirect loops because:

  • It doesn't properly handle the path component matching
  • The directive expects exact file paths, not directory trees
  • Missing proper variable interpolation for dynamic paths

Here's the correct Nginx configuration that solves this problem:

location ~ ^/images/(.*)$ {
    try_files /siteA/images/$1
              /siteB/images/$1
              /siteC/images/$1
              =404;
}

For more complex scenarios, we can extend this approach:

# Version with fallback chains
location ~ ^/static/(.*)$ {
    try_files /primary/$1
              /secondary/$1
              /legacy/$1
              @cdn_fallback;
}

location @cdn_fallback {
    proxy_pass https://cdn.example.com;
    proxy_cache my_cache;
}

When implementing multi-directory file serving:

  • Place frequently accessed directories first in the try_files list
  • Consider using open_file_cache for better filesystem performance
  • Monitor filesystem operations with stub_status module

Here's a production-tested configuration for serving web assets:

# Serve from CDN if available, then local directories
location ~* \.(?:jpg|jpeg|png|gif|ico|css|js)$ {
    try_files $uri
              /theme-assets/$uri
              /plugin-assets/$uri
              /core-assets/$uri
              @asset_proxy;
}

location @asset_proxy {
    proxy_pass https://assets.example.com;
    proxy_cache asset_cache;
    proxy_cache_valid 200 30d;
    expires max;
}

When working with multiple directory trees in Nginx, developers often need to serve files from different locations while maintaining a clean URL structure. The challenge arises when we want Nginx to:

  1. Check multiple directory paths for the requested file
  2. Serve the file directly without redirects
  3. Maintain the original URL structure

The try_files directive checks files in sequence, but the common mistake is not properly constructing the file paths. For the directory structure:

images/siteA/foo.jpg
images/siteB/b/bar.jpg
images/siteC/example.jpg

Here's the correct Nginx configuration that serves files from multiple directories without redirects:

location /images/ {
    try_files /siteA$uri
              /siteB$uri
              /siteC$uri
              =404;
}

For more complex scenarios where you need to maintain subdirectory structures:

location ~ ^/images/(.*)$ {
    try_files /siteA/images/$1
              /siteB/images/$1
              /siteC/images/$1
              =404;
}

When working with multiple directory trees:

  • Order directories by access frequency (most accessed first)
  • Consider using open_file_cache for better performance
  • Monitor filesystem operations with strace if performance is critical

For a multi-tenant SaaS application where each client has their own assets directory:

location /assets/ {
    try_files /tenants/$tenant_id$uri
              /shared/default$uri
              /shared/common$uri
              =404;
}

If you encounter issues:

  1. Check Nginx error logs (error_log)
  2. Verify filesystem permissions
  3. Test with absolute paths first
  4. Use curl -v to inspect responses