Configuring Nginx and Apache for Django

Running Django with just Apache as a server works just fine, but it isn’t the most efficient. Why? Apache works great for rendering dynamic pages, but isn’t the best for handling static files (i.e. js, css, image files). The Django documentation mentions this, in fact, as a recommendation for larger applications.

A popular way to set up a server for Django is to have Nginx serve static files and use Apache (with mod_wsgi) for rendering all the Python pages. In this quick tutorial, I’ll show you how to do just that.

Set up Apache

Chances are you probably already have Apache installed on your machine if you’re using a Linux or Mac operating system. If not, go ahead and install it:

$ sudo apt-get install apache2

You’ll also want to install mod_wsgi for Apache. Since the instructions for this vary depending on what operating system you’re using, I won’t bother mentioning the installation instructions here. You can find the instructions for your particular platform at the mod_wsgi wiki.

Configure Apache/mod_wsgi

First, we need to create a wsgi script that Apache can call to load up your Django application. In your Django application folder, create a django.wsgi file:

import os
import sys

os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

path = '/path/to/myapp'
if path not in sys.path:
    sys.path.append(path)

Be sure to edit the path and os.environ statements for your own application.

After you’ve done that, you’ll need to add your Django setup to Apache. Mod_wsgi allows you to easily do this by pointing Apache to the wsgi script we just wrote.

$ cd /etc/apache2/sites-available
$ sudo emacs default

Once you’ve opened the file, delete everything and replace it with the following:

<VirtualHost *:8000>
    ServerAdmin [email protected]
    ServerName 127.0.0.1
    WSGIScriptAlias / /path/to/myapp/django.wsgi
</VirtualHost>

Now you may have noticed that this setup looks a bit different from the usual Apache setup - our VirtualHost is configured on port 8000, not port 80. The reason we’ve done that is because we’ll be running Nginx on port 80 and you can’t run two servers on the same port.

You’ll also need to change the ports.conf file to listen/broadcast on port 8000:

$ cd /etc/apache2
$ sudo emacs ports.conf

Near the beginning of the document you should see the following two lines:

NameVirtualHost *:80
Listen 80

Change them to the following:

NameVirtualHost *:8000
Listen 8000

Now, Apache will be working solely on port 8000, so we can use Nginx on port 80. If you’re doing this on a desktop, you’ll be able to see your Django application by typing http://127.0.0.1:8000 in your browser. Note, however, that you won’t see any CSS styles or images because Apache is not set up to serve files from your staticfiles directory.

Set up Nginx

If you’re using Debian/Ubuntu, you can install Nginx from the package manager:

$ sudo apt-get update
$ sudo apt-get install nginx

You can find the download instructions for you particular platform at the nginx website.

Configure Nginx

We want to set up Nginx so that it does two things: first, it needs to serve all the static files by itself; second, if a dynamic (Django) page is needed, it will call Apache. Let’s open up the Nginx config file:

$ cd /etc/nginx/sites-available
$ sudo emacs default

Replace the contents of the file with the following statements:

server {
    listen           80;
    server_name      mysite.com;

    location /static {
        alias            /path/to/my/app/static;
    }

    location /media {
        alias            /path/to/my/app/media;
    }

    location / {
        proxy_pass       http://127.0.0.1:8000;
    }
}

Let’s break down exactly what this file means. You’re setting up a Nginx server that listens on port 80. If someone visits yoursite.com/media or yoursite.com/static, Nginx will directly serve the files. Make sure that the “alias” paths are correct for your specific application.

The last statement is the most important one here. If the visitor is not viewing a static file (i.e. they’re visiting an actual page that is loaded by Django), Nginx calls Apache to handle the request.

Now that we’ve finished editing all the files we need to, go ahead and save and close the file and restart Apache and Nginx:

$ sudo /etc/init.d/apache2 restart
$ sudo /etc/init.d/nginx restart

You should now be able to see your site normally by visiting the regular URL for your website.