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:
- Check multiple directory paths for the requested file
- Serve the file directly without redirects
- 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:
- Check Nginx error logs (
error_log
) - Verify filesystem permissions
- Test with absolute paths first
- Use
curl -v
to inspect responses