Nginx Tips & Tricks

Nginx Tips & Tricks

I’ve recently re-discovered nginx after a bit of a tussle with Apache on one large site I run. We were seeing load averages on the main site between 0.5-1.5, which to me is unacceptable. Yes, I know how to read and understand load averages, and I know that a load of 1.5 isn’t going to hurt the dual core machine. However, I like to keep things low and optimized, because there are other things that need time as well on there. Regardless, someone had forwarded me some information on [nginx](http://wiki.codemongers.com/), a lightweight, flexible web server written by a Russian guy. As it stands at the moment, nginx is actually the second most popular open-source web server on the Internet. After moving to nginx, load was reduced to a range of 0.05-0.5, which was fabulous. CPU time was also reduced by a factor of 10. Keep in mind that all I did for these changes was drop Apache 2.2 and replace it with nginx + a lot of PHP FPM processes.

Anyway, read up more on nginx yourself. I’ve got some misc stuff here that I’ve discovered / done I’m sure you’ll be interested in.

* Read the FastCGI Buffers section for hints as to why my specific instances needed so many PHP processors. YMMV.

Disabling the FastCGI Buffers

This same site I talk about above uses a custom PHP script to serve up downloads. It works by buffering around 2MB of the file in the PHP process, flushing to the client, and then repeating until the client has it all. Unfortunately, by default, most FastCGI implementations buffer data from the FastCGI backend and then serve it up to the client. This site serves files between 200MB-2GB, so buffering isn’t only not an option, if used, it kills the server within minutes from the overhead. PHP+Apache doesn’t have this problem because the SAPI obeys the flush() call in PHP, so it effectively blocks until the client receives the 2MB script buffer we set. Inside this loop, we also make calls to the database at interval to update the download “progress”, the primary reason we can’t use the X-Accel-Redirect header.

After doing some hunting around, I finally managed across some of the FastCGI source for nginx and had a look. There’s actually an undocumented configuration setting to disable this buffering behavior. Simply place in your FastCGI block this line:

fastcgi_max_temp_file_size 0;

Per [the source](http://www.riceonfire.org/lxr/http/source/http/modules/ngx_http_fastcgi_module.c?v=nginx-0.5.35),

1819
1820
1821
1822
1823
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
"the temporary files usage or must be equal or bigger than "
"maximum of the value of \"fastcgi_buffer_size\" and "
"one of the \"fastcgi_buffers\"");

I was mainly suprised to actually find this, as there’s no documentation for it in the English nginx wiki. Set it, reload, and enjoy nonbuffered data between FastCGI and nginx!

Preventing the _ Redirect

I have a rather unique configuration setup for my nginx server on this machine, whereby I use the _ parameter in the ServerName directive and craft out the rest based on the $host variable within the single server {} block. However, I was banging my head against the wall for awhile, trying to figure out with directories without the trailing slash added would 301 into http://_/dir/, but adding the trailing slash worked fine. Turns out you need this in your configuration file, outside the server block:

server_name_in_redirect off;

As it turns out, this is on by default, and internally ignores the Host: parameter when creating internal redirects, using the first host in the config file, which is, of course, _.

Setting up Trac

I used to suggest using nginx’s wsgi module, but this is no longer a recommended solution. Since then I’ve just build Apache with mod_passenger (which has nice wsgi support) and it’s been smooth sailing since. To be honest though, I got rid of Trac all together and just use Redmine now instead (which also works with mod_passenger).

Supposedly Passenger also supports Nginx, but I’ve yet to research or hear if it suffers the same issues as the wsgi module for Nginx. Proceed with caution or let me know if you ever find out.

Setting up Mercurial

Like Trac, I now suggest using Apache + mod_passenger with wsgi. I’ve had absolutely no issues since switching over to this method and it’s so braindead easy. Save yourself the effort and just do it.

One Comment

  1. Thanks for fastcgi_max_temp_file_size 0;

    saved my a$$ =)

Leave a Reply

Your email address will not be published. Required fields are marked *