Just another site

Thought this was cool: [原]Python+Django+Ubuntu+Apache+Nginx架设服务器成功记

leave a comment »


There’s a time when every Django developer has to think about deployment scenarios, when I first did it last year I thought that a setup involving

Lighty, Apache, mod_proxy and mod_python
was a good choice but my first approach was not the best. I put Apache as the front server, handling requests for Django generated pages and passing, via mod_proxy, requests for static content to Lighty on the back.
A setup where Apache had to work even for files that wasn’t supposed to serve was a very bad idea.

After many helpful comments and some more reading I realized that it was better having the server for static content on the front and Apache, which still talks to Django, on the back.

I replaced Lighty with nginx, which according to many seems to be more stable, and opted for mod_wsgi instead of mod_python to make Apache talk to Django. mod_wsgi has a lower memory overhead and it’s suitable for
high performance sites. There’s no need for mod_proxy on Apache anymore as nginx is the one in charge of the proxy work now.

This is an easy to follow and very focused guide for developers who know how to handle their servers so I won’t consider security issues, memcached, Django installation, databases or basic GNU/Linux, Apache and DNS settings. Of course all of those subjects
are important and you should take care of them.

The plan

This guide includes all the steps needed to:

  • Setup a domain for your Django project.
  • Create a simple directory layout for Django sites.
  • Configure Apache with mod_wsgi for Django.
  • Configure nginx.
  • Serve Django admin media files.
  • Turn on the heat and show your greatest and latest Django stuff to the world.

After following all the steps you will have a Django site running with nginx on the front and Apache on the back. nginx will manage all static content and will pass Django requests to Apache and mod_wsgi.

I have tested on three Ubuntu servers (two running 8.10, Intrepid Ibex, and one 7.10, Gutsy Gibbon) but everything should be pretty similar in other GNU/Linux distributions.

Shall we start?

Setup a domain for your Django project

Many of us run more than one website in one server, I have several with Drupal and a few with Django living in one box, so let’s consider a two domains scenario: will host the Django project and anything else. Most of the work will focus in, I just mention to give you some context. Obviously you should replace all the domain names in this guide with

We’ll use a couple of private IP addresses for now and will replace them with public ones and setup in a DNS server when going live. For this guide I’ll just add to
/etc/hosts, which is what I usually do in my development environment: cataybea.com192.168.0.192

I’m using and two ports, 80 and 8080, for serving the Django site at The default port 80 will be used by nginx to serve static content and Django will look for files under the
/media directory. Port 8080 will be used by Apache to handle Django requests.

Create a simple directory layout for Django sites

Directory layouts depend on personal preferences, I currently use a /home/alexis/djcode directory for all my Django coding and the new project will be called
cataybea; hence, we have to run:

mkdir /home/alexis/djcodecd /home/alexis/djcode/ startproject cataybea

Now let’s create some additional directories:

mkdir /home/alexis/djcode/cataybea/apachemkdir /home/alexis/djcode/cataybea/logsmkdir /home/alexis/djcode/cataybea/media

What are they for? apache will contain a Python script to setup mod_wsgi,
logs will store Apache and nginx logs and media is the directory nginx will use to serve static files for our Django project.

You can later manage the whole /home/alexis/djcode/cataybea directory with your favorite version control tool.

Take note of the correct paths for using later in the configuration files.

Configure Apache with mod_wsgi for Django

I assume you already have Apache working correctly and just need to tweak a little for our Django setup. As we’ll be running two web servers at once we must make sure that IP addresses and ports won’t conflict. Let’s edit

Listen 80

I have specified IP addresses and ports to listen. Notice I commented the default
Listen 80 as it means Apache would listen to that port in all IP addresses. If you want to use SSL take care of the 443 port in the same way.

If you are using virtual hosts in Apache confirm it’s listening to the correct IP addresses and ports, I have this in


Restart Apache and make sure your Apache sites work normally. I’m obsessed with testing at every step in the way and I suggest you are too.

sudo /etc/init.d/apache2 restart

Now it’s time to add mod_wsgi to Apache. The latest versions of Ubuntu have it in the repository:

sudo apt-get install libapache2-mod-wsgi

For older versions of Ubuntu, such as Gutsy, you need to find the .deb file and use something like
dpkg -i to install.

Now it’s time to create the Apache configuration file for in

<VirtualHost> ServerAdmin ServerName ServerAlias <Directory /home/alexis/djcode/cataybea/apache/> Order deny,allow Allow from all </Directory> LogLevel warn ErrorLog /home/alexis/djcode/cataybea/logs/apache_error.log
CustomLog /home/alexis/djcode/cataybea/logs/apache_access.log combined WSGIDaemonProcess user=www-data group=www-data threads=25 WSGIProcessGroup WSGIScriptAlias / /home/alexis/djcode/cataybea/apache/cataybea.wsgi</VirtualHost>

Notice the IP address and port: This site won’t be accessed directly but via proxy from nginx. We’ll set that up in the next section.

Now we need a Python script to configure our Django project to use mod_wsgi, create
/home/alexis/djcode/cataybea/apache/cataybea.wsgi and put the following code inside:

import os, sysapache_configuration= os.path.dirname(__file__)project = os.path.dirname(apache_configuration)workspace = os.path.dirname(project)sys.path.append(workspace)sys.path.append(‘/usr/lib/python2.5/site-packages/django/’)sys.path.append(‘/home/alexis/djcode/cataybea’)os.environ[‘DJANGO_SETTINGS_MODULE’]
= ‘cataybea.settings’import django.core.handlers.wsgiapplication = django.core.handlers.wsgi.WSGIHandler()

Don’t restart Apache yet as we need to complete a few more steps.

Configure nginx

nginx will do two things: serve static content from and pass all other requests to Apache. Let’s install it first:

sudo apt-get install nginx

Now remove the nginx default site:

sudo rm /etc/nginx/sites-enabled/default

Apache and nginx should be using the same user, for Ubuntu this is www-data, and your
/etc/nginx/nginx.conf should look like this:

user www-data;worker_processes 2;error_log /var/log/nginx/error.log;pid /var/run/;events { worker_connections 1024;}http { include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; sendfile on; tcp_nopush
on; keepalive_timeout 65; tcp_nodelay on; gzip on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*;}

worker_processes can be set to the number of cores in your server, in my case that’s just 2.

Configure a the site on nginx by creating /etc/nginx/sites-available/

server { listen; server_name; access_log /home/alexis/djcode/cataybea/logs/nginx_access.log; error_log /home/alexis/djcode/cataybea/logs/nginx_error.log; location / { proxy_pass; include
/etc/nginx/proxy.conf; } location /media/ { root /home/alexis/djcode/cataybea/; }}

then running:

sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

and finally creating the file that will take care of proxying Django requests to Apache, we’ll call it
/etc/nginx/proxy.conf and put this inside:

proxy_redirect off;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;client_max_body_size 10m;client_body_buffer_size 128k;proxy_connect_timeout 90;proxy_send_timeout 90;proxy_read_timeout
90;proxy_buffer_size 4k;proxy_buffers 4 32k;proxy_busy_buffers_size 64k;proxy_temp_file_write_size 64k;

Notice $host, $remote_addr and $proxy_add_x_forwarded_for are variables that will be handled by nginx, you don’t need to change anything else in proxy.conf for a basic setup. When I started playing with nginx I thought these had to be replaced by me, I was

Finally restart nginx:

sudo /etc/init.d/nginx restart

and Apache:

sudo /etc/init.d/apache2 restart

That should be it! If you visit you should see some Django content (could be the welcome page, some of your views or a 404 page depending on your project status). To try the nginx media server create a
test.htm file with some dummy content in /home/alexis/djcode/cataybea/media and visit

Serve Django admin media files (optional)

If you will use the Django admin application edit /home/alexis/djcode/cataybea/, make sure your database settings are correct, add
‘django.contrib.admin’ to the INSTALLED_APPS tuple and change the

ADMIN_MEDIA_PREFIX = ‘/media/admin/’

Let’s enable the admin url by editing /home/alexis/djcode/cataybea/, uncommenting these two lines:

from django.contrib import adminadmin.autodiscover()

and adding this to urlpatterns:

(r’^admin/’, include(,

Now let’s create a symbolic link to the media files for the Django’s administration section:

cd /home/alexis/djcode/cataybea/medialn -s /usr/lib/python2.5/site-packages/django/contrib/admin/media/ admin

And finally let’s create the administration user and the required tables in the database:

cd /home/alexis/djcode/cataybea/mediapython syncdb

As with every other modifications in your Django code you will have to reload Apache for changes to take effect:

sudo /etc/init.d/apache2 reload

Visit,including the trailing slash, and you should be in business.

Show your Django projects to the world

The nginx and Apache setup I’ve just described is pretty easy to implement and seems to be the preferred method among many Django developers. I’m using it for a new project I’m working at, you may have already guessed this, The site will be an online diary (ok, ok, a blog) where my wife and I will share some stories and tips about raising our two daughters, it will be fun.

Now that you have everything ready for deploying your next project I suggest you keep working with Django’s development server until you have everything ready to move to Apache and nginx. The development server refreshes automatically after every change
in your code so you can avoid frequent Apache reloads.

作者:quicktest 发表于2012-6-14 12:17:56 原文链接
阅读:11 评论:0 查看评论

from Wally Yu的专栏:

Written by cwyalpha

六月 14, 2012 在 5:10 下午

发表在 Uncategorized


Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: