NGINX try_files directive: Explained with examples

Updated: January 19, 2024 By: Guest Contributor Post a comment

Introduction to NGINX try_files

try_files is an essential directive in NGINX configuration which allows you to specify a list of files to try when processing a request. If NGINX cannot find the requested file, it can then fall back to the next file in the list and so on. This directive is particularly useful for serving static assets, implementing custom error pages, and creating front-controller patterns typically used by MVC frameworks.

In this tutorial, we’ll explore how to use the try_files directive effectively, with a variety of code examples to illustrate basic to advanced use cases.

Basic Usage of try_files

Let’s start with a simple example. Here’s how you can define a basic try_files directive to serve static files:

location / {
    try_files $uri $uri/ /index.html;
}

In this case, if the requested URI does not correspond to a file on the disk, NGINX will try to serve the /index.html file instead.

Output: If a request for /about is received and the file exists, it’s served directly. Otherwise, the request falls back to /index.html.

Custom Error Pages

Next, we can use try_files to handle errors with custom error pages. Consider the following:

location / {
    try_files $uri $uri/ =404;
}

This tells NGINX to return a 404 error code if none of the files are found.

Front-controller pattern for PHP Applications

Many modern PHP applications use a single PHP file as an entry point. Here’s how you can set this up:

location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

If the requested URI doesn’t match a file or directory, NGINX forwards the request to /index.php.

Advanced Configurations

Let’s dive into more complex scenarios. Assume you want to serve files with different priority. Here’s an advanced try_files:

location / {
    try_files $uri $uri.html $uri/ @fallback;
}

location @fallback {
    proxy_pass http://backend-server;
}

In this setup, if NGINX cannot serve $uri or $uri.html or the directory $uri/, it will pass the request to the fallback named location, which proxies the request to a backend server.

Now, consider leveraging caching with try_files:

location / {
    try_files /cache$uri $uri $uri/ @backend;
}

location @backend {
    proxy_pass http://backend-server;
    # Assume we also include code here for caching responses.
}

With this configuration, NGINX will first look for a cached version of the request in the /cache directory before proceeding with further options.

Dealing with Inconsistent URI Definitions

Some applications require flexibility with trailing slashes. Here’s how the try_files directive can handle this:

location / {
    try_files $uri $uri/ $uri.html /index.php$is_args$args;
}

This will attempt to serve both paths /example and /example/ before falling back to index.php.

Migrating from Legacy Applications

If you are migrating from a legacy application, you can mix and match files and named locations:


location /oldpath {
    try_files /newpath$uri /newpath$uri/ @legacyapp;
}

location @legacyapp {
    proxy_pass http://legacyapp-server;
}

In such cases, NGINX tries the new path structure first before resorting to the legacy service.

Performance Considerations

While try_files is a powerful directive, it can introduce a performance penalty if not used judiciously. Every entry in the try_files directive adds a filesystem check, which can slow down response times. It’s important to optimize the list of files and keep the most probable scenarios towards the beginning of the list.

Debugging try_files

When troubleshooting configurations with try_files, you can use NGINX’s debug logging. You’ll need to compile NGINX with the --with-debug option and set the error_log level to debug. This provides detailed output of the processing of try_files directives to help pinpoint issues.

Conclusion

In summary, the try_files directive in NGINX is a versatile tool for managing the handling of requests and the delivery of resources. Whether you’re managing static assets, implementing custom error pages, routing to a PHP front controller, or handling complex legacy migrations, try_files provides a concise and powerful way to direct traffic. As with all NGINX directives, judicious use and careful testing are the keys to maintaining performance and reliability in your web services.