THIS IS OUTDATED DOCUMENTATION. NEW VERSION AVAILABLE HERE:
Media Temple is End-Of-Life-ing their Grid Server Django Containers. As such, I had to migrate all my django sites off the grid onto a new (VE) server. This is a guide for building a stock CentOS 5.5 server with django and python 2.7.
// SHOUT OUTS
Malcolm Frazier – Holding it down with all the linux knowledge.
// USER ACCOUNTS
The first step is to create a user account so you don’t have to use root
# useradd <username> # passwd <username>
Add a user group so we can setup the sudoers file and add our new user account to the group
# /usr/sbin/groupadd <new_group_name> # /usr/sbin/usermod -a -G <new_group_name> <new_user_name>
I like to use the locate command a lot, so lets build the index of file names to search from
Setup the sudoers config file
# vim /etc/sudoers
Add the following lines to the bottom of the file:
# Customizations %<new_group_name> ALL=(ALL) ALL
At this point you should be able to exit ssh and log back in as your new user account. You can use sudo <command> to execute commands as root, or use sudo -s as a replacement for su.
// UPGRADE PACKAGES SYSTEM WIDE
# yum upgrade
// INSTALLING PYTHON 2.7
I’ve chosen to use Python 2.7 as my version of python for django. CentOS comes with Python 2.4 already installed. I had some down time on a project because I asked the techs at RackSpace to upgrade the version of python on the server and they started by trying to uninstall Python 2.4. The problem is that the yum package management system that CentOS uses is built on top of python. If you uninstall python 2.4, you will not be able to use yum to install python 2.7, or any package at that point. The solution is to install Python 2.7 in parallel to 2.4, have Django and all your other apps use the 2.7 install, and leave 2.4 to be used by yum.
Theres a great tutorial on installing Python 2.7 on CentOS 5 here.
Instead of using /usr/src/ for all the source code, I created /root/Source/ to hold the source from all the packages. Inside of Source, download and extract Python 2.7:
# wget http://www.python.org/ftp/python/2.7/Python-2.7.tar.bz2 # tar -xvjf Python-2.7.tar.bz2 # cd Python-2.7 # ./configure --help
Read through the configure help and see if there are any options you want to enable or customize. Then ./configure
# ./configure --prefix=/usr/local/python2.7
–prefix tells the configure script to install python into /usr/local/python2.7/ to create a completely separate parallel installation next to python 2.4.
Because of a mod_wsgi error that you will run into later, you should install the following dependencies before installing python:
# yum install readline-devel # yum install gdbm-devel # yum install sqlite-devel
After installing the dependencies, you can run ./configure again after you do a # make clean. This will get rid of the old config file and generate a new one.
# make clean # ./configure --prefix=/usr/local/python2.7
Assuming everything went well, build and install python 2.7
# make # make install
// SETUP ENVIRONMENT VARIABLES
$ vim ~/.bashrc
Add the following to the bottom of .bashrc:
# User specific aliases and functions alias python='/usr/local/python27/bin/python'
Log out, Log back in, and you should be able to execute the new Python 2.7
$ python Python 2.7 (r27:82500, Mar 22 2011, 13:20:42)
// INSTALLING PIL (PYTHON IMAGING LIBRARY)
At this point, if you install PIL without first satisfying dependencies, PIL will be built without libjpeg and zlib (png support). The output of python setup.py install would be:
*** TKINTER support not available *** JPEG support not available *** ZLIB (PNG/ZIP) support not available *** FREETYPE2 support not available *** LITTLECMS support not available
Unfortunately, PIL doesn’t complain very loudly and will still install a working version that will not be able to handle .jpg or .png files. If you install PIL without the header libraries for the dependencies present, you will receive the following error in django’s admin when trying to upload a file:
Upload a valid image. The file you uploaded was either not an image or a corrupted image.
You can further verify if the proper support is compiled in from the shell:
$ python >>> from PIL import Image >>> i = Image.open("/path/to/some/image.jpg") >>> i.verify() >>> i.load() Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/local/python2.7/lib/python2.7/site-packages/PIL/ImageFile.py", line 189, in load d = Image._getdecoder(self.mode, d, a, self.decoderconfig) File "/usr/local/python2.7/lib/python2.7/site-packages/PIL/Image.py", line 385, in _getdecoder raise IOError("decoder %s not available" % decoder_name) IOError: decoder jpeg not available
You can see from the above error that the jpeg decoder is not available. If you’ve already installed PIL, uninstall it. If you havn’t installed PIL yet, this will save you a lot of time (:
# yum install zlib zlib-devel # yum install libjpeg libjpeg-devel # yum install freetype freetype-devel
Django relies heavily on the Python Imaging Library PIL. Again in our /root/Source/ directory, install PIL
# wget http://effbot.org/downloads/Imaging-1.1.7.tar.gz # tar xvfz Imaging-1.1.7.tar.gz # cd Imaging-1.1.7 # python setup.py build_ext -i
Check to make sure that libjpeg and zlib were found:
*** TKINTER support not available --- JPEG support available --- ZLIB (PNG/ZIP) support available --- FREETYPE2 support available *** LITTLECMS support not available
Run a test to make sure that everything works:
# python selftest.py -------------------------------------------------------------------- PIL 1.1.7 TEST SUMMARY -------------------------------------------------------------------- Python modules loaded from ./PIL Binary modules loaded from ./PIL -------------------------------------------------------------------- --- PIL CORE support ok *** TKINTER support not installed --- JPEG support ok --- ZLIB (PNG/ZIP) support ok --- FREETYPE2 support ok *** LITTLECMS support not installed -------------------------------------------------------------------- Running selftest: --- 57 tests passed.
And finally, install PIL
# python setup.py install
You should now be able to import PIL inside of python:
$ python >>>import PIL >>>
// INSTALLING APACHE
Next we have to install our web server, Apache. Theres a pretty straight forward tutorial on this here.
# yum install httpd # /sbin/chkconfig httpd on # /etc/init.d/httpd start Starting httpd: [ OK ]
At this point, you should spend some quality time with /etc/httpd/conf/httpd.conf to really squeeze some power out of apache.
// INSTALLING MOD_WSGI
mod_wsgi is the link between apache and django. It is responsible for taking the web request from apache, and getting it to your django app for handling. The mod_wsgi installation docs are a great resource, they can be found here.
First, we need to install the source code for apache, as mod_wsgi needs it to build. Install the httpd-devel package, which will install the headers for apache.
# yum install httpd-devel
Get and install mod_wsgi, again from /root/Source/
# 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 # ./configure --help # ./configure --with-python=/usr/local/python27/bin/python # make # make_install
// INSTALLING PHPMYADMIN
PhpMyAdmin is a web interface for controlling your MySQL database. The RPM for PhpMyAdmin is in the rpmforge repo, so we will add that repo to yum. Again from /root/Source/:
# wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm # rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt # rpm -K rpmforge-release-0.5.2-2.el5.rf.*.rpm # rpm -i rpmforge-release-0.5.2-2.el5.rf.*.rpm # yum search phpmyadmin # yum install phpmyadmin
Setup the PHP Cookie
# vim /usr/share/phpmyadmin/config.inc.php
Add the Python Shared Libraries
# vim /etc/ld.so.conf.d/python2.7.conf
add the following line:
// INSTALLING DJANGO
The django install docs can be found here.
# wget http://www.djangoproject.com/download/1.3/tarball/ # tar xzvf Django-1.3.tar.gz # cd Django-1.3 # python setup.py install $ python >>> import django >>>
// POINT APACHE AT DJANGO USING MOD_WSGI
First, you need to tell apache which version of python to use so it doesn’t use the built in 2.4
# vim /etc/httpd/conf/httpd.conf
Add the following to the bottom of the file
#Python Versioning Control for mod_wsgi WSGIPythonHome /usr/local/python2.7
Then restart apache
# /etc/init.d/httpd restart
Now you can configure your virtual hosts in apache to point to a ‘django.wsgi’ file thats specific to your django project. Add the WSGIScriptAlias to your Virtual Host
WSGIScriptAlias / /path/to/your/django/project/django_project_name/apache/django.wsgi
Add the ‘apache’ directory to your django project, and copy the following into django.wsgi inside of the apache folder
import os import os.path import sys sys.path.append('/path/to/project/root') os.environ['PYTHON_EGG_CACHE'] = '/path/to/a/directory/for/egg_cache' os.environ['DJANGO_SETTINGS_MODULE'] = 'your_django_project_name.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
If you’ve made it this far, you should have a working django install.