Nginx Understanding the intersection of alias and try_files

September 23, 2018

via GIPHY

Background

When working with Nginx it is important to understand the routing and built-in variables. I was working on a clients server configuration recently and we ran into what seemed to be a very annoying bug within Nginx. To frame the issue, they needed to route to different folders based on sub-domains in order serve the clients static files.

The Architecture

This architecture consisted of docker containers with Nginx behind, an Amazon ELB, behind Amazon CloudFront. We needed to handle SSL termination for multiple custom domains however, Amazon only allows you to use one certificate per load balancer. So we were doing SSL termination within Cloudfront for a custom domain like ‘example.com’ which would then need to be converted to ‘example.exampleapp.com’. This allowed us to separate SSL termination out for different parts of the stack.

What We Had to Solve

Nginx needed to then take the sub-domain and route asset requests to different folders within the docker container. Given the example above example.com would need to go to /var/www/sites/example.com/public. This needed to happen in a programmatic way in order to avoid having a different server block per sub-domain. So Alias seems perfect for this right? So we started off with a server block that looks like this.

server {
    ...
    index /var/www/app

    location ~/([a-zA-z0-9_]+)/assets/([a-zA-Z0-9_\/\.]+)$ {
        alias /var/www/$1;
        try_files $uri $uri/ /index.php;
    }

    ...
}

I kept reading through the docs and thinking it looked exactly like the example in the Nginx docs. I even switched out Alais with root, to test a specific case and everything worked… So what was going on?

The First Solution

After reading the docs over and over, and getting nowhere I turned to stack overflow. I found this post and thought I struck Gold. It;s a long-standing bug, it said. My job is done, it doesn’t work in Nginx move on to the next option. The truth is we are all developers and despite finding that I hammered the app for another couple hours. I logged out the document root and thought it just confirmed my theory since Alias was working correctly.

The Real Solution

I decided to try one more thing, and I removed the try_files line, and everything worked. At this point, I was 100% convinced it was a core bug. I was curious though why this was a bug and decided to log out $uri. The second I did that it all clicked. $url is not affected by Alias, so it was re-adding the entire URI to try files and looking in a directory that didn’t exist. Finally, I went back to that stack overflow post and realized what was actually going on. I needed to use the regex value in try_files and not a core variable. So we ended up with the following solution which works perfectly.

server {
    ...
    index /var/www/app

    location ~/([a-zA-z0-9_]+)/assets/([a-zA-Z0-9_\/\.]+)$ {
        alias /var/www/$1;
        try_files $2 $2/ /index.php;
    }
    ...
}

Conclusion

The biggest thing to understand about Nginx is its routing, and how it modifies its variables. What looked like a core bug, was really just the misuse of $uri.


comments powered by Disqus