New Nginx.conf with optimizations

Posted by ezmobius Wed, 03 Jan 2007 22:28:00 GMT

I have been working on optimizing my nginx.conf file as I use it on more and more sites. Thanks to folks on the nginx and mongrel mailing lists for some of these fixes. Main improvements is in gzip of dynamic and other content as well as setting the proxy buffers to 0 and a few improvemets in the proxy header settings. This conf also includes a second vhost for ssl that points to the same mongrel cluster so you can hanlde ssl and non ssl with the same cluster and rails request.ssl? helper will work correctly.

Another big improvement is with static file handling. The credit on this one goes to Zed Shaw. He notcies that the rewrites and regex tests for rails cached pages were getting run for every request including static images. So a request for /images/foo.jpg woudl get served in this manor:

/images/foo.jpg/index.html  # no file found continue
/images/foo.jpg.html  # no file found continue
/images/foo.jpg # good send it!

This is obviously a performance hit for static files as it has two extra regexes and two extra file stats for every static image. Suck, I wish I found this sooner. To fix this all we need to do is add this test right at the top before the other rewrite tests:

      # If the file exists as a static file serve it directly without
      # running all the other rewite tests on it
      if (-f $request_filename) { 
In my benchmarks this does increase the speed of static files about 8%. Also allowing gzip on HTTP 1.0 requests made sure that the proper static assets are gzipped when possible. Also we force all proxied requests to be gzipped if they are the right content type. I also added more gziped content types and corrected a wrong one for javascript.

This is an important lesson about your production environment folks. With regards to what you accept as gospel from someone like me. “Trust but verify”. Zed was trying to track down how to do a custom rewrite for alternate cache directories and so he at my behest turned on the debug logging and consequently saw the rewrites happening on every static file. I haven’t been in the rewrite log for a while since I thought my config was good. So when you get config files from people like me off the net, please trust but verify on your own systems.

This new config is running close to 100 instances of nginx at Engine Yard. Nginx has proven to be an excellent choice for a front end proxy balancer for mongrel. It beats apache in all my tests now as far as non gzipped proxy requests, static file requests and it ties with apache for gzipped proxy requests. And its about 30 times more lightweight then apache.

If you were holding off to try nginx until it was proven out by others then let me tell you it has proven itself to me time and time again already as a very easy to manage, high performance options for rails deployment on mongrel. I don’t personally use apache2.2 right now for anything other than mod_svn for subversion over HTTP. But there is stirring of upcoming support for nginx and svn over webdav so stay tuned. When that happens I will happily drop apache from our rotation entirely. Of course take this with a grain of salt as always, I don’t have to support any php apps or legacy stuff right now, just rails. I haven’t personally used php with nginx yet but I see others getting fantastic results so I am not worried for when I may need it.

All in all this new config file performs significantly better then my old one. Somewhere on the order of 20% total improvement overall over the last config file. I have updated the link to poitn from the old article to the right confi file and I am linking it here again for your enjoyment:

New Nginx.conf

Tags , , , ,  | 17 comments


  1. Yan said about 1 hour later:
    Thanks Ezra! We're running nginx in production for (only 2 instances, not 100 like you :-). We've had it up for a month at a time with no noticeable issues. Of course we made the blunder of treating your config as gospel truth (with minor mods), so these improvements are very nice. Thanks for continuing to explore nginx to benefit all of us in the community. You're in a unique position with engine yard to test our things at a large scale that most of us don't get to do until we make it big. Nginx feels like a very well engineered piece of software. The config is straightforward enough, and 'it just works' for the most part. It also works great when you bounce mongrels in the background, no complaints there!
  2. Xian said about 2 hours later:
    It looks like you've got some erb bits left in there in the ssl section <%= server_name %> + etc.
  3. Ezra said about 4 hours later:
    @Yan- thanks for the kind words.

    @Xian- good catch. I'm a fan of templated config files and I forgot to remove those erb tags. I have fixed them now. Thanks
  4. Dan Kubb said 2 days later:

    I like to make sure that my static assets are cached so I use something like this:

    location ~ ^/(images|javascripts|stylesheets)/ {
      expires 10y;

    This causes the browser to cache the files for 10 years. If you're using helper methods like image_tag, javascript_include_tag and stylesheet_link_tag the timestamp of the file will be apended to the query string. When the file physically changes, the URL will change which will "bust" the cache and cause the browser to request the new file.

  5. Ezra said 2 days later:
    Dan- cool, I'll add that one. Any other suggestions from anyone? Dan do you put that at the top of your vhost?
  6. null said 2 days later:

    Ezra, I put that underneath the block for "location /". I don't know precisely how Nginx processes multiple location blocks, like whether it stops at the first match, or if it processes all blocks that match the URI (similar to Apache), but I assume its closer to the latter since this seems to work for me.

    One question, is it necessary to specify the "root" again in the "location = /500.html" block? I thought since it's already specified in the outer block that it defines the root globally for the server.

    Another thing I've been doing is using "internal" for blocks corresponding to URIs I don't want to expose to the outside world. My "location = /500.html" block uses it for example. I didn't think it was necessary to allow access to URIs for my support files.

  7. David Vrensk said 5 days later:

    Not the right forum, perhaps, but on topic, I hope: has anyone figured out a way to have nginx log the value of certain cookies?

    I'm reading through my mongrel logs to learn more about a wierd intrusion attempt, and I'm reminded that it would be nice to see more of the original headers in the log. (Yes, I can see the session id in mongrel's logs, but I'd like to find any matching entries for plain files.)

  8. Rafael Lima said 12 days later:
    Hi, I've configured nginx with ssl support. Every time I reboot the server, nginx is asking for a password and the server do not finish the power off process. What can I do to avoid it? Thanks!
  9. Sebastian Friedrich said 20 days later:
    Ezra, i'll be forever grateful to you for introducing me to nginx. Now running 7 rails apps on a new dedicated server courtesy of nginx+mongrel_cluster and i couldn't be happier with it. Thanks for the config. Btw, in case you still wonder, PHP support is flawless. Just installed Squirrelmail using nginx and spwan-fcgi (from lighttpd distro) and it works like a charm. Also, i couldn't find a startup script anywhere out there, so i threw one together for Ubuntu/Debian ( @Rafael: You need to recreate your certificate key without a password phrase. Removing the -des3 flag will do that.
  10. Chris said 23 days later:
    I appreciate your introducing me to nginx a few months ago and, even more so, your keeping on top of the power tips for it. Nginx has proven to be awesome and I don't miss having to deal with Apache! :D
  11. Walter McGinnis said 28 days later:
    You mention that you only use apache2 for svn over http. I'm doing the same thing for the same reasons (mod_dav_svn). Mine is sitting behind nginx just like my mongrel clusters. What I would like to do is use http for non-committer checkouts and https for committers. I'm half way there, as http is for the public. However, I use svn+ssh for committers, but it would be nice to allow commits to people outside of my organization without having to give them an account on the host. Have you figured out a way to configure nginx/apache2 config for svn to "fake out" apache2 much like how rails request.ssl? is persuaded that it's got an https request? Is this line in the ssl server enough? # needed for HTTPS proxy_set_header X_FORWARDED_PROTO https; I'll give it a try and see, but feel free to point me in the right direction. Cheers, Walter
  12. Dan Kubb said 30 days later:
    Ezra, the log_format used in your configuration is similar to, but not close enough to Apache's "combined" log format that it can be parsed by popular log stats programs. The problem lies in the ordering of the options in the config. Right now you have $status after the $time_local, but combined format has $status after the $request, but before $body_bytes_sent.
  13. Ezra said 33 days later:
    Thanks Dan, I had made that change in my local configs and forgot to update the on here on my blog. I just fixed it.
  14. Geoff said 59 days later:
    Running a few php sites and rail sites through nginx (trying to exit php ASAP) - apache mod-security used to make us sleep better at night against cross-scripting and injection attacks - anybody been fiddling with regex's in nginx as a substitute. Would rather nip in the bud at the server rather than go back and rewrite some very old legacy PHP stuff
  15. Christopher said 62 days later:
    Ezra: I am trying to determine the behavior of the rewrite rules. You mentioned the rewrite log in your post. Where is that and how do you turn it on? I can't seem to discern it from the documentation.
  16. Alan said 78 days later:
    Ezra: can you describe your config setup? Templated config files?
  17. Mauro Cicio said 120 days later:
    Ezra: fantastic work, thanks!

    In the current version of the config file we find:
     # needed for HTTPS
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect false;
    proxy_max_temp_file_size 0;
    The # needed for HTTPS comment might be misleading.
    Not needing https, I commented these lines out and this made me hit the problem described by Kevin Marsh and rick in your previous blog New Nginx Conf with Rails Caching.
    The problem was about http://mongrel popping up when using something like (home_path route).
    Putting the lines back in solved the issue.

(leave url/email »)

   Preview comment