Our Django Server Setup: How and Why
Recently updated on
One of the most important decisions you make in the process of building a new Django application is what software stack you use to serve it to the world. You're not lacking for options: people run Django on Apache, lighty, nginx, and Cherokee. You also need to decide how to connect Django to your webserver. Popular choices are mod_python, mod_wsgi, and fastcgi. Django also supports multiple database backends, including PostgreSQL, MySQL, SQLite, and Oracle.
What follows is a description of the software and setup we use at Imaginary Landscape, along with explanations for why we made these choices. At the end of the post is a quick-and-dirty guide to getting this setup off the ground from scratch.
Web Server: Nginx
Much of our pre-Django development has been in the Paste framework, which is heavily dependent on Apache. When we decided to start development in Django, we took it as an opportunity to move away from Apache and find a lighter, quicker http server. We looked around at the options and eventually settled on nginx. Here's why:
Speed
Ease of use
Native memcached support
Native fastcgi support
In-house benchmarking tests confirmed that serving a Django app via nginx was significantly quicker than serving the same app via Apache. Switching to nginx also cut down the size of our config files, making them easier to parse and comprehend. The memcached support is great for increasing the available cache size and reducing database load. Native fastcgi support brings us to...
Web Server Connector: FastCGI
You have probably figured out by this point that we chose to use FastCGI over WSGI. Here's why:
Natively supported by our webserver
Allows use of unix domain sockets
Separation of web process from python process
FastCGI support is built in to nginx, which makes it quick and easy to configure. FastCGI also supports the use of unix domain sockets to connect to the python process, instead of using TCP sockets. Because all of our software is on one server, there's no reason to pass requests through a TCP socket. A unix domain socket is faster, and more secure. The last bullet point is very important for me - I love having the web server process separate from the python process. It allows me to reload each process at will without affecting the other, and I can easily monitor memory and CPU usage for each process individually. This becomes vital when you run multiple dozen Django instances on a single server.
Database: PostgreSQL
This is one instance where I stick with the Django recommendation. We use PostgreSQL for our database backend, because it's what the Django developers use. The framework/database interaction is a bit more complicated than the framework/webserver interaction, and so I prefer to go with the option that's going to cause the least trouble. Also, we've been using PostgreSQL here at Imaginary Landscape for years, and we've found it easier to configure and manage than MySQL.
So there you have it. The Imaginary Landscape Django server configuration. Hopefully it's been informative! Comments and questions are welcome.
Postscript - quick and dirty setup guide:
install PostgreSQL (from package manager or source)
install nginx (from source)
create user and group for your new site
install virtualenv, a tool to create isolated Python environments (from pypi)
create virtualenv for your new site
install flup, a Python library for dealing with FastCGI (from pypi)
install Django (from pypi)
create a new Django project
create a database user and database
install psycopg2 (from initd.org)
update settings.py with your db info
create nginx configs
start nginx process
start fcgi process
test!
We've created some in-house tools which make this process a bit more streamlined, but this gives you a general idea of the steps needed to get it going.