Nginx's try_files
directive performs sequential file existence checks in the specified order until it finds a match. The syntax follows:
try_files file ... uri;
try_files file ... =code;
Key characteristics:
- Evaluates paths left-to-right
- Stops at first found file
- Requires final parameter as fallback
- Treats trailing slashes as directory markers
For your specific cache scenario, here's the correct implementation:
location / {
try_files /path/app/cache/$uri/index.html /path/app/cache/$uri/index.php $uri /index.php;
}
This configuration will:
- Check for cached HTML version
- Check for cached PHP version
- Fall back to original URI
- Finally use index.php as ultimate fallback
Frequent issues developers encounter:
# Incorrect: Missing final fallback
try_files /cache/$uri /main_site; # Will cause 500 error if both fail
# Correct: Proper fallback
try_files /cache/$uri /main_site/index.php?$query_string;
Combine with named locations for complex routing:
location / {
try_files $uri $uri/ @backend;
}
location @backend {
include fastcgi_params;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
For static asset handling with multiple cache layers:
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
try_files /cdn-cache/$uri /local-cache/$uri $uri;
expires 30d;
access_log off;
}
Order your try_files
paths strategically:
- Place most frequently accessed paths first
- Put lightweight checks before expensive ones
- Consider filesystem I/O overhead
For production environments, combine with open_file_cache
:
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
The try_files
directive in Nginx is often misunderstood despite being one of the most powerful tools for request handling. Let me explain its actual behavior through practical examples.
The syntax try_files path1 [path2...] fallback
means:
- Nginx checks each path sequentially
- If a path ends with slash (/), it looks for index files (index.html, index.php, etc.)
- The first found file that exists is served immediately
- If none found, performs internal redirect to the fallback URI
For your scenario of checking cache first, then falling back to PHP, here's the correct implementation:
location / {
try_files /path/app/cache$uri/index.html
/path/app/cache$uri/index.php
$uri $uri/ /path/app/index.php?$args;
}
Several important notes about try_files
behavior:
- The directive checks files in the order specified, not automatically checking index files unless trailing slash is present
- Parameters (
$args
) are only preserved automatically when falling back to named locations - The fallback parameter must exist or Nginx returns 500 error
Here's a more complete example with FastCGI integration:
location / {
try_files $uri $uri/ /cache/$uri/index.html
/cache/$uri/index.php @fallback;
}
location @fallback {
include fastcgi_params;
fastcgi_pass unix:/var/run/php-fastcgi/php-fastcgi.socket;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
If your configuration isn't working:
- Verify file permissions (Nginx needs read access)
- Check error logs (
tail -f /var/log/nginx/error.log
) - Test paths manually using
ls -la
to confirm existence - Use
strace
to debug file access attempts