blog: Creating My Django Server.

Posted on 07 Dec 2008 under

(Note: This article is essentially a walk through of what I did to setup Django on a basic Ubuntu Intrepid server. Any comments or suggestions on improving my setup are more then welcome as I do not claim to be an expert at setting up web servers, just a tinkerer)

Whether you’re writing your application in Python, Ruby, or even PHP (Yes, even PHP) it feels good to know what’s exactly powering your software. Earlier this week I put together the setup for one of my Django sites and this guide will go through the process. The services are running off a 256mb slice from Slicehost, which I highly recommend.

What we’re running here: The end result is an Ubuntu Intrepid server using Apache2 with mod_python to serve Django, and lighttpd to serve media/static files. Memcache is used as a caching backend and mySQL 5.0 is our primary database. This is a very common Django setup and you will find similar guides all over the net. This is just my take :)

Getting the packages we need.

SSH to your server, authenticate and run the following commands to install our necessary packages:


    $ sudo aptitude install apache2 apache2.2-common apache2-utils

    $ sudo aptitude install libapache2-mod-python

    $ sudo aptitude install python-setuptools # You need this for a few python modules we need to install

    $ sudo aptitude install mysql-server mysql-client libmysqlclient15-dev

    $ sudo aptitude install memcached

    $ sudo aptitude install python-mysqldb

    $ sudo aptitude install lighttpd</code>

Setting up MySQL.

Setting up mySQL is rather simple. You already supplied a root password when you were initially installing the packages so all we really need to do now is create a database and grant access to a non-root user. This is very simple:


    $ mysql -uroot -p

    mysql> CREATE DATABASE mysite;

    mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON mysite.* TO 'foo'@'localhost'  IDENTIFIED BY 'password';

As I said, very simple. We create an initial database and then use GRANT to give us a user/password combo we can connect with. If you have an existing set of mysql data, you can now dump it into your database.

I don’t fancy myself an expert in mySQL user permissions so I recommend viewing the mySQL 5 Grant Documentation for more information. You may also want to take a look at your /etc/mysql/my.cnf configuration file to modify mySQL settings depending on your sites load.

Configure & run memcached as a daemon

Installing memcached is optional as you may not need or want caching, but it’s generally good practice to have it with your Django sites. To run it, we are going to execute this command:


    $ memcached -u www-data -p 11211 -m 32 -d

What this does is tells memcached to run under the user www-data which is the user Apache runs under on Ubuntu. We run it on port 11211 (default), and give it 32mb of memory. You can adjust this memory to be larger or smaller depending on your machine and traffic of websites. As I only have 256mb of RAM and a single (small) site, this is sufficient. Finally, the -d flag runs it as a daemon.

Now we have to install some memcached python bindings. cmemcache is a popular choice but I can’t get it to work when installing memcached from a package (only from source, which we didn’t do), so we opt for the second best: python-memcached. Simply grab it and install it:


    $ wget ftp://ftp.tummy.com/pub/python-memcached/python-memcached-latest.tar.gz

    $ tar -zxvf python-memcached-latest.tar.gz

    $ cd python-memcached-1.43

    $ sudo python setup.py install

That’s pretty much it for memcached! The rest of the work is involved within your Django application which you can read all about from the official Django documentation.

Setup Django.

Of course, we actually need to get Django! You can fetch it in a variety of ways from the download page. Personally, I enjoy using the SVN trunk as it’s pretty stable while having the benefit of new features and bug fixes as soon as they are done. I like setting up Django in /home and then linking it to site-packages. This allows me to not worry much about permissions and everything just seems easier. Plus I love the ~ accessibility :)

First, let’s give our www-data user (see above, it’s our Apache user) access to our files.


    $ sudo gpasswd -a www-data yourusername # In my case, it's admin

    $ chmod g+w ~

Now, let’s get Django from trunk and setup some directories for our projects.


    $ cd ~

    $ mkdir projects

    $ mkdir apps # This is not used in the tutorial, but this is where I place my portable django apps

    $ svn co http://code.djangoproject.com/svn/django/trunk/ django

    $ sudo ln -s `pwd`/django/django /usr/lib/python2.5/site-packages</code>

That’s it for that. Django is now recognized as a package in Python’s sys.path

Setting up your project with Apache.

We’re almost there! Now, we finally need to tell Apache and mod_python that we have a Django project we want them to serve. If you have an existing project, simply fetch it from your favourite version control service. If not, you can start your own project quite simply:


    $ cd ~/projects

    $ ~/django/django/bin/django-admin.py startproject myproject

If you are starting from scratch, you will need to modify your settings.py file to match our setup of a mySQL database and the usage of memcached. There’s no point in me iterating over this, as the Django docs explain it quite well. So let’s get right down to it and setup our domain in Apache.


    $ sudo vim /etc/apache2/sites-available/myproject.tld

And then paste the following, modifying as needed:


    <VirtualHost *>
        ServerName www.myproject.com
        ServerAlias myproject.com

        DocumentRoot /var/www/myproject.com

        CustomLog /var/log/apache2/myproject.com.access.log combined
        ErrorLog /var/log/apache2/myproject.com.error.log

        SetHandler python-program
        PythonHandler django.core.handlers.modpython
        SetEnv DJANGO_SETTINGS_MODULE myproject.settings
        PythonDebug On
        PythonPath "['/path/to/my/projects/parent_dir'] + sys.path"

        <Location "/media">
            SetHandler None
        </Location>

    </VirtualHost>

Some quick notes:

- Replace /path/to/my/projects/parent_dir and myproject.settings to the relative values. The path is to your projects PARENT directory. So in my case, it would be /home/bartek/projects

- /media is the directory where our django’s admin media will be linked to.

- Depending on your DNS settings, you may need to adjust the wildcard on the VirtualHost declaration.

Finally, let’s enable the site and setup the admin media link:


    $ sudo ln -s /etc/apache2/sites-available/myproject.com /etc/apache2/sites-enabled/myproject.com

    $ sudo ln -s ~/django/django/contrib/admin/media /var/www/myproject.com/

    $ sudo apache2ctl restart # Restart Apache

…….And if you did everything right you should see either your Django project running or the default “It works!” Django page. Congrats!

Setting up lighttpd

Lighttpd setup is optional, but is highly recommended. It’ll keep your site running smoothly and doesn’t bog down Apache/mod_python trying to serve both Django and media.

First, you’ll have to edit Lighttpd’s settings to run on a different port. The default is 80, which is what our Apache setup is running on:


    $ sudo vim /etc/lighttpd/lighttpd.conf

Uncomment the server.port line (around line 70)


    server.port               = 81

Next, enable the mod_evhost module. Simply uncomment it in the server.modules variable near the top of the config file. mod_evhost allows you to use a different directory for the static media depending on the domain name. Now, add the following line which basically says requests for myproject.com should look in this directory. I did this on the 124th line, right after the evhost patterns.


    $HTTP["host"] =~ "myproject\\.com" {
        evhost.path-pattern = "/home/admin/projects/myproject/static/"
    }

Just so you’re not confused, I generally place my media in my project directory like I did above but you can have it anywhere you want. A commonplace is under /var/www/myproject.com

Note: If you are under Debian/Ubuntu and your site has a “images” directory, the default lighttpd config may not serve this. Some Debian/Ubuntu configurations reference “images” as a dir for the Debian policy and all your images will be broken unless you remove this reference. I found it at around line 160.

Start lighttpd:


    $ sudo /etc/init.d/lighttpd start

And verify it is working by visiting http://myproject.com:81. You should see either your Apache or Lighttpd placeholder page.

Configure Apache to use Lighttpd

To serve files using Lighttpd from Apache we need to enable proxy on Apache. There are other methods of doing this, but I’ve found this the best documented, and hey — it works great!


    $ ln -s /etc/apache2/mods-available/proxy.load /etc/apache2/mods-enabled/

    $ ln -s /etc/apache2/mods-available/proxy_connect.load /etc/apache2/mods-enabled/

    $ ln -s /etc/apache2/mods-available/proxy_http.load /etc/apache2/mods-enabled/

Or just as easily type sudo a2enmod proxy proxy_connect proxy_httpd if you are under Ubuntu. Finally, unsecured proxies are used by spammers so we want to configure ours to only accept local connections. Simply do this:


    $ sudo vim /etc/apache2/mods-available/proxy.conf

And modify the wildcard in <VirtualHost> to state the local host like so:


    AddDefaultCharset off

    Order deny,allow

    Deny from all

    Allow from 127.0.0.1

Finally, configure the VirtualHost to use the Proxy


    $ sudo vim /etc/apache2/sites-available/myproject.com

Add this somewhere in your <VirtualHost> declaration


    ProxyRequests Off

    ProxyPreserveHost On

    ProxyPass /static http://127.0.0.1:81/

    ProxyPassReverse / http://127.0.0.1:81/

And with that setup, reload and restart Apache and Lighttpd should now be serving your static media!


    $ sudo /etc/init.d/apache2 reload

    $ sudo /etc/init.d/apache2 restart

To double check if it is, you can use the lovely Firebug plugin and just look under the “Net” tab or just use curl:


    $ curl -I http://myproject.com

    $ curl -I http://myproject.com:81

Curl will send back a response on what is serving it. You’ll see the first one shows Apache/mod_python, and the second line should return a lighttpd reference.

It works!

And that about wraps it up! There are many things you can do to customize the services running your software but this is a basic setup that works great for small and medium-scale sites. From here, you can extend this by setting up PHP for other apps, and securing your server. I recommend the articles on Slicehost for some great walk throughs on securing your server.

References & Credits:

Of course, there are many people who have done this long before me and I got a lot of information from. These posts outline what I did, but in their own manner and some have other useful information. I recommend checking them all out as they are great at what they do:

Thanks for reading!

Others Posts You May Enjoy

Thanks for reading. How about leaving a comment?

blog comments powered by Disqus
Fork me on GitHub