27
Sep

Static files with Nginx + Passenger

posted by gchatz 5 comments nginx rails

Normally, when you setup Nginx and Passenger to serve your rails application, all static files are served by Nginx without hitting Passenger. What really happens is that all static files that do exist are served by Nginx and the rest are passed on to passenger.

For example

http://www.mydomain.com/javascripts/prototype.js

will be served by Nginx , but

http://www.mydomain.com/javascripts/iamastupidrobot.js

will continue to Passenger going all the way through the Rails stack. Instead of a simple 1ms nginx process , you get a full stack rails request with a route recognition error. Not good.

Missing or outdated images (specially if your site is big on content) or stupid robots searching for certain *.php (or *.js, or _vti_bin(?) or whatever) vulnerable files is common place. Why would you want those requests to pass on to passenger?

Using an asset host

One solution is to use an asset host for all static files by using an absolute url like

<script type="text/javascript" src="http://assets.mydomain.com/javascripts/prototype.js"></script>

instead of

<script type="text/javascript" src="/javascripts/prototype.js"></script>

Then you can make a separate entry for nginx for assets.mydomain.com with just a root directive to your public directory. This way static files will always be served by nginx, even the missing ones.

In addition you can specify multiple asset hosts and tell Rails to cycle through them. This is especially good for splitting the load among multiple servers and bypassing the 2 requests per ip browser constraint. What I don’t like with this approach is that simple image tags have to go through the image_tag helper, causing some overhead for no good reason.

Configure Nginx

        set $asset F;

        if ($request_filename ~* ".*\.(gif|jpg|css|jpeg|png|bmp|asp|php|_vti_bin|js)$") {
             set $asset T;
        }

        if (!-f $request_filename) {
             set $asset "${asset}T";
        }

        if ($asset = TT)
        {
                return 404;
                break;
        }

The first condition sets $asset to ‘T’ if the requested file is a static file (or a file that Rails doesn’t care about).
The second condition sets $asset to ‘TT’ if the requested file doesn’t exist.
The third condition breaks the rewrite flow and returns a 404.

There you go!

Comments (5)

Pin Phi.Sanders said on Oct 15, 04:38 PM:

Awesome site, but I can't subscribe in my news reader since your RSS feed is broken...

Pin دردشه said on Jan 27, 04:25 PM:

Found it a great launch
I thank you very much
Appreciation and respect
Heck on the theme of Creative Commons
Kois gone by and Hloowoowo ..

Pin دردشة said on Feb 10, 07:26 PM:

Awesome site, but I can't subscribe in my news reader since your RSS feed is broken...

Pin New Gadgets said on Feb 19, 04:58 PM:

Yeah Paypal is quite usefull. But i find it even more impressive that people are constantly working to improve this genius payment system. Thank your for this tutorial, its very useful.

Pin منتديات said on Feb 23, 11:51 PM:

Found it a great launch
I thank you very much
Appreciation and respect
Heck on the theme of Creative Commons
Kois gone by and Hloowoowo ..

Drop a comment: