Understanding Nginx’s try_files Directive: A Comprehensive Guide with Practical Examples


2 views

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:

  1. Check for cached HTML version
  2. Check for cached PHP version
  3. Fall back to original URI
  4. 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:

  1. Nginx checks each path sequentially
  2. If a path ends with slash (/), it looks for index files (index.html, index.php, etc.)
  3. The first found file that exists is served immediately
  4. 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:

  1. Verify file permissions (Nginx needs read access)
  2. Check error logs (tail -f /var/log/nginx/error.log)
  3. Test paths manually using ls -la to confirm existence
  4. Use strace to debug file access attempts