Ben Godfrey

All posts tagged “nginx”

Announcing aftnn.org version 2.0

Version 2.0 of aftnn.org is here!

The new site is powered by the Byteflow with a few some custom bits. Byteflow runs on top of Django.

Some of the features I’m happiest about:

  • My FriendFeed collects all the stuff I’ve been doing on the web and I re-use that feed here.
  • The vast majority of old urls still work. My nginx config contains a rewrite line for each blog post. Not pretty, but fast.
  • The Content and Photos sections are dynamically generated, making them easier to maintain.
  • I can finally write blog posts in Markdown, not raw HTML. Byteflow actually allows me to select a text renderer per-post, so I can write one post in Markdown, the next in MediaWiki markup.
  • Comments are hosted locally again, not by Intense Debate, and are protected by CAPTCHA. Alternatively, you can log in with your OpenID to comment.
  • nginx serves up static content very quickly and gzips everything too.

There are always some down-sides though.

  • Blanket is gone. It was a resource hog and I didn’t want to port it to Python. Sorry.
  • Byteflow and Django don’t play as nicely with caches as I would like. Byteflow doesn’t provide Last-Modified, Expires or ETag headers for it’s pages. Django sets cookies immediately, instead of when a session is actually used, so it’s page are effectively uncacheable. Also, Django does not provide Content-Length headers for responses. All this degrades the performance of my site.
  • The Intense Debate comment import process lost the threading. I’ll try to fix the relevant posts by hand some time.

I hope you like the new site. Please post a comment if you find a bug or have any other feedback.

Nginx+Django+FastCGI

A lot of people seem to have posts like this, but there were some things that I got stuck on when moving to Nginx from Apache.

location ^~

The ^~ match can not be used with regular expressions.

This will not work as expected:

location ^~ /(foo|bar)/ {
    ...
}

Use the ~ match operator if you want to use an RE. Make sure that your RE matches don’t clash with you plain string matches. The latter will be preferred in this event.

location + root

If you want to specify a different root within a location block, be mindful that the uri is unchanged.

For example, if you want to publish Django’s admin media, you might write something like this:

location ^~ /admin/media/ {
    root /usr/local/django/django/contrib/admin/media;
}

When a request comes in, Nginx will concatenate the root and the uri to find the file to server. With this config, it will try to serve /usr/local/django/django/contrib/admin/media/admin/media/css/base.css.

SCRIPT_NAME and PATH_INFO

Django uses PATH_INFO to match against urlpatterns. Nginx’s fastcgi_params include doesn’t set that. It does set SCRIPT_NAME. If both PATH_INFO and SCRIPT_NAME are set to $fastcgi_script_name, Django seems to get an empty path for all requests. Just set PATH_INFO!

Request buffering to file

Nginx buffers large requests to file before passing them to an upstream server. There is no option to stop this from happening. If you want to track the progress of request uploads, you will need to use the Upload Progress Module.