This step-by-step tutorial walks you through the installation of Django 1.1 with Apache and MySQL. on CentOS 5. The example VPS used during the walk-through is the popular SliceHost from RackSpace ™ The steps involved should be quite similar for any properly installed CentOS 5.x (or RedHat EL 5.x).

We use the latest stable version of Python: 2.6 and mod_wsgi (far superior alternative to mod_python), in this tutorial. Django is not, yet, compatible with Python 3.x branch (few things are).

Note: this tutorial is partially based on: a blog post by Matt Reiferson

Set up user

We will first log-in as root and set up environment for a user with the username “irakli” (you can use your own username).

[root@django ~]# groupadd webmaster
[root@django ~]# useradd -c "Irakli" -g webmaster -m -s /bin/bash irakli
[root@django ~]# passwd irakli
Changing password for user irakli.
New UNIX password: 
Retype new UNIX password: 
passwd: all authentication tokens updated successfully.
[root@django ~]# visudo

Add a line like “irakli ALL=(ALL) ALL” under similar “root ALL=(ALL) ALL” line (by default line #77) to grant your new user sudo access and avoid the necessity of using root account.

[root@django ~]# sudo su - irakli
[irakli@django ~]$ sudo hostname yourhostname.com
  • Add entry into /etc/hosts to point public ip address to yourhosntame.com
  • Edit /etc/sysconfig/network to set hostname
  • sudo-edit /etc/bashrc and add following code after the original umask logic (around line 14):\

    if [ $UID -gt 99 ] && [ "`id -gn`" = "webmaster" ]; then
            umask 002
    fi
    

Install Apache, MySQL and miscellaneous tools

[irakli@django ~]$ sudo yum install httpd-devel mysql mysql-server mysql-client mysql-devel apr-devel
[irakli@django ~]$ sudo yum install openssl mod_ssl crypto-utils
[irakli@django ~]$ sudo yum install libjpeg libpng gcc make autoconf telnet libxslt gettext
[irakli@django ~]$ sudo yum install bind bind-utils bind-devel
[irakli@django ~]$ sudo yum install zlib-devel
[irakli@django ~]$ sudo yum install postfix # I like postfix over sendmail
  • Make sure your /etc/httpd/conf/httpd.conf includes a line like:\

    Include conf.d/*.conf
    
  • sudo mkdir /var/www/default
  • sudo vi /etc/httpd/conf.d/00_default.virtualhost.conf in there enter:\

    NameVirtualHost *:80
    
    <VirtualHost *:80>
        DocumentRoot /var/www/default
        ServerName _default_
        ErrorLog logs/default-error_log
        CustomLog logs/default-access_log common
    </VirtualHost>
    
  • sudo vi /var/www/default/index.html
    in there enter your default message for misconfigured hosts:

    Default blank page
    

Upgrading Python

[irakli@django ~]$ python -V
Python 2.4.3
[irakli@django ~]$ cd ~/
[irakli@django ~]$ mkdir src
[irakli@django ~]$ cd src
[irakli@django src]$ wget http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tgz
[irakli@django src]$ tar xzvf Python-2.6.4.tgz
[irakli@django src]$ cd Python-2.6.4
[irakli@django Python-2.6.4]$ ./configure --prefix=/opt/python2.6 --with-threads --enable-shared --with-zlib=/usr/include
[irakli@django Python-2.6.4]$ make
[irakli@django Python-2.6.4]$ sudo make install
[irakli@django Python-2.6.4]$ sudo ln -s /opt/python2.6/lib/libpython2.6.so /usr/lib
[irakli@django Python-2.6.4]$ sudo ln -s /opt/python2.6/lib/libpython2.6.so.1.0 /usr/lib
[irakli@django Python-2.6.4]$ sudo /sbin/ldconfig -v
[irakli@django Python-2.6.4]$ sudo ln -s /opt/python2.6/bin/python /usr/local/python
[irakli@django Python-2.6.4]$ python -V
Python 2.6.4 

Troubleshooting: if you still see old version of Python, you need to edit /etc/profile (as root), add the following line:

pathmunge /opt/python2.6/bin/

towards the end of the file, before the line that reads something like:

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC

and re-login to the system, so that new path location is picked up by the system. Then try running “python -V” again.

[irakli@django ~]$ sudo yum search php # make sure we did not accidentally mess up “yum”, which is the biggest threat when upgrading Python version. If you see no errors, you should be fine

Installing Python Extensions

[irakli@django Python-2.6.4]$ cd ..
[irakli@django src]$ wget http://bit.ly/6E0DNN
[irakli@django src]$ sudo su -
[root@django ~]# cd /home/irakli/src/
[root@django src]# chmod u+x setuptools-0.6c11-py2.6.egg 
[root@django src]# ./setuptools-0.6c11-py2.6.egg --prefix=/opt/python2.6
[root@django src]# exit
logout                                        

# (For some reason installing MySQL-python .egg binary, we downloaded, did not work. Let's show how to install it from source, if you run into a similar problem):

[irakli@django src]$ wget http://bit.ly/6j4uID
[irakli@django src]$ tar xzf MySQL-python-1.2.3c1.tar.gz 
[irakli@django src]$ cd MySQL-python-1.2.3c1
[irakli@django MySQL-python-1.2.3c1]$ python setup.py build
[irakli@django MySQL-python-1.2.3c1]$ sudo python setup.py install
[irakli@django MySQL-python-1.2.3c1]$ cd ..
[irakli@django src]$ python 
Python 2.6.4 (r264:75706, Nov 29 2009, 19:51:34) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import MySQLdb
(you should not see any errors, type Ctrl-D to exit)

Install Django

[irakli@django src]$ wget http://www.djangoproject.com/download/1.1.1/tarball/
[irakli@django src]$ tar xzf Django-1.1.1.tar.gz 
[irakli@django src]$ cd Django-1.1.1
[irakli@django Django-1.1.1]$ python setup.py build
[irakli@django Django-1.1.1]$ sudo python setup.py install

[irakli@django Django-1.1.1]$ cd ..
[irakli@django src]$ python
Python 2.6.4 (r264:75706, Nov 29 2009, 19:51:34) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.VERSION
(1, 1, 1, 'final', 0)
>>> import MySQLdb

Starting a Django Project

Note: for former PHP developers, it’s important to understand that Django project not only does not have to, but also should not be in a web-accessible folder. An installatio that has Django project under a DocumentRoot is inherently insecure.

[irakli@django src]$ sudo mkdir -p /opt/web/django
[irakli@django src]$ sudo chown irakli:webmaster -R /opt/web
[irakli@django src]$ sudo chmod -R 775 /opt/web
[irakli@django web]$ cd /opt/web/django
[irakli@django django]$ /opt/python2.6/bin/django-admin.py startproject iproj
[irakli@django django]$ cd iproj

Configure Apache with mod_wsgi

[irakli@django django]$ cd ~/src
[irakli@django src]$ sudo ln -s /opt/python2.6/lib/python2.6.so /opt/python2.6/lib/python2.6/config/
[irakli@django src]$ wget http://modwsgi.googlecode.com/files/mod_wsgi-2.8.tar.gz
[irakli@django src]$ cd mod_wsgi-2.8
[irakli@django mod_wsgi-2.8]$ ./configure --with-python=/usr/local/bin/python
[irakli@django mod_wsgi-2.8]$ make
[irakli@django mod_wsgi-2.8]$ sudo make install
[irakli@django mod_wsgi-2.8]$ cd ~/src

[irakli@django src]$ vi /opt/web/django/iproj.wsgi

import os
import sys

sys.path.append('/opt/web/django')
os.environ['DJANGO_SETTINGS_MODULE'] = 'iproj.settings'
os.environ['PYTHON_EGG_CACHE'] = '/opt/web/django/iproj/.python-eggs'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()


[irakli@django src]$ mkdir /opt/web/django/iproj/.python-eggs
[irakli@django src]$ sudo chmod -R 777 /opt/web/django/iproj/.python-eggs

[irakli@django src]$ mkdir /opt/web/django/iproj/logs
[irakli@django src]$ sudo chown apache:staff -R /opt/web/django/iproj/logs
[irakli@django src]$ sudo chmod -R 775 /opt/web/django/iproj/logs

[irakli@django src]$ sudo vi /etc/httpd/conf.d/yourdomain.com.conf

<VirtualHost *:80>
  ServerName yourdomain.com

  ErrorLog /opt/web/django/iproj/logs/error_log
  CustomLog /opt/web/django/iproj/logs/access_log combined

  UseCanonicalName Off

  Alias /admin_media /opt/python2.6/lib/python2.6/site-packages/django/contrib/admin/media
  Alias /static /opt/web/django/iproj/static

  WSGIScriptAlias / /opt/web/django/iproj.wsgi
  WSGIDaemonProcess iproj processes=7 threads=1 display-name=%{GROUP}

</VirtualHost>

[irakli@django conf.d]$ sudo /etc/init.d/httpd configtest
Syntax OK

Configure Firewall

  • sudo vi /etc/sysconfig/iptables-config and make sure following variables are set to “yes”:
    IPTABLES_SAVE_ON_STOP=”yes”
    IPTABLES_SAVE_ON_RESTART=”yes”

    Open Web ports:

  • sudo /sbin/iptables -I INPUT -p tcp -m state –state NEW,ESTABLISHED –dport 80 -j ACCEPT
  • sudo /sbin/iptables -I INPUT -p tcp -m state –state NEW,ESTABLISHED –dport 443 -j ACCEPT
  • Restart iptables with: ‘sudo /sbin/service iptables stop’ and: ‘sudo /sbin/service iptables start’ and make sure rules are still in. Try restarting server, too, to make sure setting picked up.
[irakli@django conf.d]$ sudo /etc/init.d/httpd restart

Open http://yourdomain.com you should see a Django welcome screen.

Add Startup Scripts

These will ensure, your servers will come back up after a server reboot.

  • sudo /sbin/chkconfig –add httpd
  • sudo /sbin/chkconfig –level 2345 httpd on
  • sudo /sbin/chkconfig –list httpd

     

  • sudo /sbin/chkconfig –add mysqld
  • sudo /sbin/chkconfig –level 2345 mysqld on
  • sudo /sbin/chkconfig –list mysqld

     

  • sudo /sbin/chkconfig –add postfix
  • sudo /sbin/chkconfig –level 2345 postfix on
  • sudo /sbin/chkconfig –list postfix

Have fun writing Django programs!