Running Django 1.3 on CentOS 5.5

This post teaches you how to set up a CentOS 5.5 virtual server in the cloud, and install Django 1.3.  There is a lot of information about this scattered around the Internet, but I haven’t seen one post putting it all together. Unfortunately it’s more complicated than just “yum install python django” because CentOS 5.5 relies on python 2.4 for some system-level stuff, and Django 1.3 needs a more modern python than 2.4. So I use virtualenv to have python 2.7 installed and running alongside the CentOS python 2.4. If you already have CentOS up and running simply skip the part about setting up a server for the first time.

First, set up a virtual server in the cloud. I recommend Rackspace.

Use the Rackspace web interface to create a Linux server instance. This post uses CentOS 5.5. CentOS is Red Hat without the monthly fees.

Use the Rackspace web interface to discover your public IP address, and ssh in using your root account. I know this feels really dirty and wrong, but we’ll fix that right away. Get the root password from the email rackspace sends you when you reset the password. Alternatively, use the rackspace web console to do this root account dirtiness.

Pick a username for yourself, like hampsterhuey. As root create your account (lines beginning with # are to be typed at the shell)

# useradd hampsterhuey
# passwd hampsterhuey

(type your password, like gooeykablooie)

Now change the root password
# passwd

Still as root, add yourself to the wheel group
# vi /etc/group

find the line in /etc/group that looks like
wheel::10:root

change to:
wheel::10:root,hampsterhuey

Save the file. Now give yourself sudo power by running
# /usr/sbin/visudo

find the lines
## Allows people in group wheel to run all commands
# %wheel  ALL=(ALL)       ALL

Add to end to not type password on sudo
hampsterhuey ALL=(ALL) NOPASSWD: ALL

uncomment the %wheel line.

save the sudoers file. Now that hampsterhuey is at full power, we can stop stomping around as root.
# vi /etc/ssh/sshd_config

Find this section in the file, containing the line with “PermitRootLogin” in it. Edit it to say “no” like this

#LoginGraceTime 2m
#PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6

* Now you’ll need to restart the sshd service:
# sudo /etc/init.d/sshd restart

Log out of your instance and try to ssh in as root. It won’t work. Ssh in as yourself to continue.

Add /sbin and /usr/sbin to your path in the file .bash_profile in your home directory to avoid driving yourself insane.

install apache and mysql
# sudo yum -y httpd
# sudo yum -y mysql

If you start apache at this point
# sudo /etc/init.d/httpd start
it won’t allow connections! You need to put a hole in your firewall. The default iptables config doesn’t allow incoming TCP on port 80.

This page can explain IPTables to you, or just follow my instructions.
http://wiki.centos.org/HowTos/Network/IPTables

Edit /etc/sysconfig/iptables. Open up 80 and 443 to allow http and https with these lines in your config:

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

They fit in like this:

# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT

ha! ha! Manual configuration not recommended! Good one!

now restart iptables and apache
# sudo /etc/init.d/iptables restart
# sudo /etc/init.d/httpd restart

and visit your public IP in your web browser of choice to verify it works. You should see a simple page saying “It works!”

Now we compile python 2.7.2. Unfortunately you can’t use the CentOS package system to install this version of python, or any recent version. CentOS 5.5 ships with Python 2.4.3, and it relies on that version of python for various system-level tasks.

Make yourself a directory for source code
# cd
# mkdir src
# cd src

Download the python package
# wget http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tar.bz2
# tar jxvf Python-2.7.2.tar.bz2
# cd Python-2.7.2

Now compile python. I’ve added some options to the configure script to install python into /opt. I like to install custom packages into /opt to keep track of them. Running make altinstall instead of make install creates binaries with the version number attached, like python2.7 instead of python. We have to do that to avoid colliding with the python binaries on the system that are version 2.4.
# ./configure --enable-shared --prefix=/opt --exec-prefix=/opt
# make
# sudo make altinstall

Now we compile mod_wsgi 3.3. This is how Apache talks to Django.

# cd
# cd src
# wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
# tar zxvf mod_wsgi-3.3.tar.gz
# cd mod_wsgi-3.3
# declare -x LD_LIBRARY_PATH="/opt/lib"
# ./configure --with-python=/opt/bin/python2.7
# make
# sudo make install

Now if you tried to restart apache you’d have shared library problems. Let’s fix that.

# sudo cp /opt/lib/libpython2.7.so.1.0 /usr/lib64
# sudo ln -s /usr/lib64/libpython2.7.so.1.0 /usr/lib64/libpython2.7.so

Now edit /etc/httpd/conf/httpd.conf

at the top of Section 1 add
WSGIPythonHome /opt/virt-env

among the other mod_’s add
LoadModule wsgi_module modules/mod_wsgi.so

restart Apache
sudo /etc/init.d/httpd restart

Now you’re running apache with mod_wsgi compiled against python 2.7.2 like a boss.

Now install virtualenv, here is a page explaining what it is.
http://pypi.python.org/pypi/virtualenv

Same as before, change directory to ~/src
# cd ~/src
# wget http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.6.4.tar.gz#md5=1072b66d53c24e019a8f1304ac9d9fc5

etc…

Now we install the mysqldb python library under a virtual environment using virtualenv.

# cd /opt
# sudo mkdir /virt-env
# sudo virtualenv --no-site-packages --python=/opt/bin/python2.7 virt-env/
# source /opt/virt-env/bin/activate
# sudo pip install --upgrade MySQL-python

Now after all that, we install Django. Python has several package managers. This tutorial uses pip. For this to work, you must still be in the “virtual environment” created when you ran the command # source /opt/virt-env/bin/activate.

#sudo pip install Django

To get Django working, edit httpd.conf. Find the line:
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

and add this line right after it

WSGIScriptAlias / /opt/momsrobotco/apache/django.wsgi

Add the following to the Alias section:

Alias /robots.txt /usr/local/wsgi/static/robots.txt
Alias /favicon.ico /usr/local/wsgi/static/favicon.ico

AliasMatch ^/([^/]*\.css) /usr/local/wsgi/static/styles/$1

Alias /media/ /usr/local/wsgi/media/
Alias /static/ /usr/local/wsgi/static/

<Directory /usr/local/wsgi/static>
Order deny,allow
Allow from all
</Directory>

<Directory /usr/local/wsgi/media>
Order deny,allow
Allow from all
</Directory>

WSGIScriptAlias / /usr/local/wsgi/scripts/django.wsgi

<Directory /usr/local/wsgi/scripts>
Order allow,deny
Allow from all
</Directory>

Now edit /usr/local/wsgi/scripts/django.wsgi to look like this. Replace your “path =” line with the location of your Django project.

import os
import sys
path = '/opt/django/momsrobotco'
if path not in sys.path:
sys.path.append(path)

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

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

Now install MySQL using regular CentOS tools.
# yum -y install mysql-server
#mysql -u root -p

(no password, just hit enter)
Now use SQL language to create your Django database for your project, and add the username and password to your settings.py. Here is what this should look like.

CREATE DATABASE momsrobotco;
CREATE USER 'momsrobotco'@'localhost' IDENTIFIED BY "cool password";
GRANT ALL PRIVILEGES ON momsrobotco.* TO 'momsrobotco'@'localhost' WITH GRANT OPTION;

Now upload your django project to the server, Make sure to put it in the same directory as the “path =” line in django.wsgi. When running django behind apache, be aware that there is a lot of caching going on (unlike when using the development server on your local machine). This mean you’ll have to restart Apache when you make changes, and sometimes even then your changes will not show up for a while. Long story short, don’t try to develop a site on a machine running django behind Apache.

When you’re doing django stuff, make sure to run the line
# source /opt/virt-env/bin/activate
First. Then when you type “python” it will load python 2.7 instead of python 2.4. So if you want to muck around at the shell, get into your project directory and type:
python manage.py shell

I hope this tutorial was useful for you! I’ll try to help anyone who posts a comment. Also check out #django on IRC, those guys helped me out big time.

Advertisements

One thought on “Running Django 1.3 on CentOS 5.5

  1. awsolutions says:

    Whats the etc part?

    Same as before, change directory to ~/src
    # cd ~/src
    # wget http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.6.4.tar.gz#md5=1072b66d53c24e019a8f1304ac9d9fc5
    etc…

    Because /configure doesn’t work here…so whats the etc?

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: