In part 2 of this series, we got PostgreSQL up and running. In this part, we’ll install the remaining components to get Django up and running under Apache: Apache itself, Python 2.6, psycopg2, and mod_wsgi.

So far, we’ve just accepted the default configuration parameters that initdb provided. Those will get us up and running, and setting the various PostgreSQL config parameters is worth at least one post all to itself. (In the meantime, see Josh Berkus’ talk “The Mighty GUCS”.)

Installing Apache couldn’t be easier:

1[xof@blog ~]$ sudo yum install httpd httpd-devel

(We need httpd-devel to build mod_wsgi, the module we’ll use to get at Python programs from Apache.)

Python and Centos: A Brief Diversion

The good news about Python on Centos is that it comes pre-installed. (It has to be; yum, among other tools, is written in Python.) The bad news is that the version that it comes with is …

1[xof@blog ~]$ python -V
2Python 2.4.3

… not exactly current. The most recent version of Python on the 2.x line as of this writing is 2.6.3. The very bad news is that you cannot just upgrade the base system Python install to 2.6; it breaks some of the system tools.

Fortunately, a solution exists: Doing a parallel installation of Python. I’m deeply indebted to this posting from Perplexed Labs for guidance on the process.

On with it: Installing Python 2.6

Since the RPMs for Centos are all Python 2.4, we need to install Python 2.6 from source. So, we grab the tarball, download it, and install it.

1[xof@blog ~]$ cd builds
2[xof@blog builds]$ wget http://www.python.org/ftp/python/2.6.3/Python-2.6.3.tgz
3[xof@blog builds]$ tar xvfz Python-2.6.3.tgz
4[xof@blog builds]$ cd Python-2.6.3

Note the --prefix option to put the 2.6 install in a different location.

1[xof@blog Python-2.6.3]$ ./configure --prefix=/opt/python2.6 --with-threads --enable-shared
2[xof@blog Python-2.6.3]$ make
3[xof@blog Python-2.6.3]$ sudo make install

Add a symbolic link to put Python 2.6 in our path:

1[xof@blog Python-2.6.3]$ sudo ln -s /opt/python2.6/bin/python /usr/bin/python2.6

Add the shared libraries to ldconfig and to /usr/lib64:

1[xof@blog Python-2.6.3]$ sudo sh
2sh-3.2# cat >> /etc/ld.so.conf.d/opt-python2.6.conf
3/opt/python2.6/lib
4sh-3.2# /sbin/ldconfig
5sh-3.2# exit
6[xof@blog Python-2.6.3]$ cd /usr/lib64
7[xof@blog Python-2.6.3]$ sudo ln -s /opt/python2.6/lib/libpython2.6.so.1.0 libpython2.6.so.1.0
8[xof@blog Python-2.6.3]$ sudo ln -s libpython2.6.so.1.0 libpython2.6.so

How does it look?

1[xof@blog Python-2.6.3]$ python2.6
2Python 2.6.3 (r263:75183, Oct 17 2009, 18:29:55)
3[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
4Type "help", "copyright", "credits" or "license" for more information.
5>>>

Great. Onwards.

Installing setuptools

It’s very handy to have the Python package setuptools, so let’s download that and install it from the appropriate Python egg:

1[xof@blog Python-2.6.3]$ cd ..
2[xof@blog builds]$ wget http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c9-py2.6.egg
3[xof@blog builds]$ sudo sh setuptools-0.6c9-py2.6.egg --prefix=/opt/python2.6

Installing psycopg2

And now we can install psycopg2. First, I have to say that the documentation on pretty much any aspect of psycopg2 is not exactly everything one can ask for; reading the INSTALL file in the tarball is your friend…

1[xof@blog builds]$ wget http://initd.org/pub/software/psycopg/psycopg2-2.0.13.tar.gz
2[xof@blog builds]$ tar xvfz psycopg2-2.0.13.tar.gz
3[xof@blog builds]$ cd psycopg2-2.0.13

One of the files in the tarball is setup.cfg; this contains a setting we need to fix. We point pg_config to the right location for the binary.

1# "pg_config" is the preferred method to locate PostgreSQL headers and
2# libraries needed to build psycopg2. If pg_config is not in the path or
3# is installed under a different name uncomment the following option and
4# set it to the pg_config full path.
5pg_config=/usr/local/pgsql/bin/pg_config

And away we go!

1[xof@blog psycopg2-2.0.13]$ python2.6 setup.py build
2[xof@blog psycopg2-2.0.13]$ sudo python2.6 setup.py install

So, did that work?

1[xof@blog psycopg2-2.0.13]$ python2.6
2Python 2.6.3 (r263:75183, Oct 17 2009, 18:29:55)
3[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
4Type "help", "copyright", "credits" or "license" for more information.
5>>> import psycopg2
6>>> conn = psycopg2.connect("dbname='template1' user='postgres' host='localhost'")
7>>> cur = conn.cursor()
8>>> cur.execute("""SELECT datname from pg_database""")
9>>> rows = cur.fetchall()
10>>> print rows
11[('template1',), ('template0',), ('postgres',)]

Installing mod_wsgi

mod_wsgi is an Apache module serving up Python programs. It’s generally considered a superior candidate to mod_python.

1[xof@blog builds]$ wget http://modwsgi.googlecode.com/files/mod_wsgi-2.6.tar.gz
2[xof@blog builds]$ tar xvfz mod_wsgi-2.6.tar.gz
3[xof@blog builds]$ cd mod_wsgi-2.6
4[xof@blog mod_wsgi-2.6]$ ./configure --with-python=/opt/python2.6/bin/python
5[xof@blog mod_wsgi-2.6]$ make
6[xof@blog mod_wsgi-2.6]$ sudo make install

To be paranoid, we should check two things. One: Did it link against the correct Python shared library?

1xof@blog mod_wsgi-2.6]$ ldd /usr/lib64/httpd/modules/mod_wsgi.so
2 linux-vdso.so.1 => (0x00007fffcbbfe000)
3 libpython2.6.so.1.0 => /opt/python2.6/lib/libpython2.6.so.1.0 (0x00007f9ac3553000)
4 libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f9ac332c000)
5 libdl.so.2 => /lib64/libdl.so.2 (0x00007f9ac3128000)
6 libutil.so.1 => /lib64/libutil.so.1 (0x00007f9ac2f25000)
7 libm.so.6 => /lib64/libm.so.6 (0x00007f9ac2ca1000)
8 libc.so.6 => /lib64/libc.so.6 (0x00007f9ac294b000)
9 /lib64/ld-linux-x86-64.so.2 (0x000000323e400000)

Looks good. Second, how big is the shared library it created?

1xof@blog mod_wsgi-2.6]$ ls -l /usr/lib64/httpd/modules/mod_wsgi.so
2-rwxr-xr-x 1 root root 339625 Oct 17 23:02 /usr/lib64/httpd/modules/mod_wsgi.so

We’re looking for a size in the 332 kilobyte or smaller range, to confirm that it linked against the Python library as a shared, not static, library; for a discussion of this issue, see the “Lack of Shared Library” heading in the installation instructions.

In the next part, we’ll configure Apache, install Django, and bring up a test application.