Django on cpanel with python2.6, virtualenv and mod_wsgi
Here is the simple to follow step by step tutorial on howto run latest Django on cpanel powered servers with python 2.6, virtual env and mod_wsgi.
If you are running cPanel on your server it's most probably a rhel or centos distro, and those will have by default python2.4 installed. You can't just overwrite your python2.4 as many of the system utilities are depended on the python2.4 So what we will do is install an alternate python 2.6 and setup our server to run Django instances with python2.6
First of all let's make a folder where we will download all those source packages
Installing python and dependencies
mkdir -p /usr/src/python26 && cd /usr/src/python26
Next, we have to download and install sqlite3 dependency. It's not needed if your Django instances will not run sqlite databases, but on a safe side it's better to install it than not.
wget http://www.sqlite.org/sqlite-amalgamation-3.6.4.tar.gz
tar zxvf sqlite-amalgamation-3.6.4.tar.gz
cd sqlite-3.6.4
./configure
make
make install
If all went well it's time to install python 2.6 as alternate install.
cd /usr/src/python26 wget http://www.python.org/ftp/python/2.6.5/Python-2.6.5.tgz tar zxvf Python-2.6.5.tgz cd Python-2.6.5 ./configure --prefix=/opt/python2.6 --with-threads --enable-shared make make install
This will install python 2.6 in /opt/python2.6 and will not interfere with system python install. Let's make a symbolic link to our newly installed python:
ln -s /opt/python2.6/bin/python /usr/bin/python2.6<
Also we must instruct our system where it should find the libs for new python.
echo '/opt/python2.6/lib' >> /etc/ld.so.conf.d/opt-python2.6.conf ldconfig
You shoud check if your new python install is working as it should:
/usr/bin/python2.6 Python 2.6.5 (r265:79063, Jul 15 2010, 16:55:23) [GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
Type CTRL+D to exit. Next thing to do is installation of python-setup tools:
cd /usr/src/python26 wget http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c11-py2.6.egg sh setuptools-0.6c11-py2.6.egg --prefix=/opt/python2.6
Make sure to define the prefix on where your new python 2.6 installation is residing. We should make a temporary alias for new python as it will be needed for installation of python mysql package:
alias python="/opt/python2.6/bin/python"
Let's check if everything is working ok:
python Python 2.6.5 (r265:79063, Jul 15 2010, 16:55:23) [GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> CTRL + D
So next in line is mysql for python:
cd /usr/src/python26 wget http://netcologne.dl.sourceforge.net/project/mysql-python/mysql-python/1.2.3/MySQL-python-1.2.3.tar.gz tar zxvf MySQL-python-1.2.3.tar.gz cd MySQL-python-1.2.3 python setup.py build python setup.py install
Again let's verify the install:
cd /usr/src/python26 python Python 2.6.5 (r265:79063, Jul 15 2010, 17:57:29) [GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sqlite3 >>> import MySQLdb >>> CTRL + D
It shouldn't return any errors while issuing import statements. Ok for the end let's install the virtualenv so we can create a virtual python enviroment for each user and his Django instances
cd /opt/python2.6/bin
./easy_install virtualenv
And here we conclude the python instalation. Next order of business is mod_wsgi
mod_wsgi installation
cd /opt/python2.6/lib/python2.6/config/ ln -s ../../libpython2.6.so . cd /usr/src/python26 wget http://modwsgi.googlecode.com/files/mod_wsgi-3.2.tar.gz tar zxvf mod_wsgi-3.2.tar.gz cd mod_wsgi-3.2 ./configure –with-python=/opt/python2.6/bin/python make make install
This will install mod_wsgi in /usr/local/apache/modules/mod_wsgi.so Note that this wsgi module is built with python 2.6 and will not work with any other version. All we have to do now is add the mod_wsgi in our apache conf. You can do that on cpanel servers via WHM. Log into WHM , click on Apache Configuration then Include Editor then Pre-Virtualhost Include and select All versions Paste this:
LoadModule wsgi_module /usr/local/apache/modules/mod_wsgi.so AddHandler wsgi-script .wsgi
** Save and restart apache.** And that's it. Our apache is now ready to serve python scripts via mod_wsgi Now all we have to do is install some Django instances for our user.
Setting up Django projects
I'll use '[username] ' for cpanel username reference and '[domain] ' for that user's domain. To match your needs you will have to replace those where appropriate. First of all you will have to decide if you will do empty virtual environments so that the user can decide what python site-packages will he use or will you preinstall some packages so that user can only update his virtualenv with packages that are missing. If you are choosing the first method user will have to have compile rights under security setting of cpanel WHM otherwise he will not be able to install packages as python mysql, PIL and some others. If you choose the former method you can preinstall those packages systemwide for our alternate python install, but whenever you update those packages all virtual environments will be updated with them. It's a matter of personal preference. I for myself rather like the clean virtualenv, and before delivering it to the client you as root preinstall in his virtualenv those packages requiring gcc rights. So let's create a virtualenv for our user:
cd /home/[username] /opt/python2.6/bin/virtualenv --no-site-packages --distribute virtualenv chown -R [username].[username] virtualenv
this will create a new directory __ /home/[username]/virtualenv __ with our new virtual python environment for our user. You will have to enable normal shell for this user, let's first check what shell this user has.
cat /etc/passwd |grep [username]
it should return something like this:
[username]:x:928:923::/home/[username]:/usr/local/cpanel/bin/jailshell
This user has jailshell enabled to change that into normal shell do this:
usermod -s /bin/bash [username]
You can also do this via WHM-> Manage Shell Access. From this point on we will do everything as the user and not root, until told otherwise.
su [username] source virtualenv/bin/activate
And the promt will change to something like this:
(virtualenv)[username]@[domain] [~]#
that way we know we are loged in as user and we are using his virtualenv. Now let's install Django in this users environment, simply enter:
easy_install django
Now is also a good time to install additional python site-packages like mysql and PIL. First temporarily enable compilers for this user via WHM->Compiler Access->Allow specific users to use the compilers do the modules install with:
easy_install [module_name]
disable the compiler access afterwards
So we have the django installed inside the users virtualenv, all we have to do now is start one of the instance. It's probably the best practice to keep django sites outside of public_html folders on cpanel servers. So we will do (still as a user)
cd mkdir djangosites cd djangosites django-admin.py startproject [projectname]
So by now we should have a directory structure like this:
/home/[username]/virtualenv < - python virtual environment /home/[username]/djangosites <- django sites folder /home/[username]/djangosites/[projectname] <- django project
Create the wsgi script for that project, usualy [projectname].wsgi in django sites folder
nano /home/[username]/djangosites/[projectname].wsgi
and paste the following code:
import sys import site import os vepath = '/home/[username]/virtualenv/lib/python2.6/site-packages' prev_sys_path = list(sys.path) site.addsitedir(vepath) sys.path.append('/home/[username]/djangosites') new_sys_path = [p for p in sys.path if p not in prev_sys_path] for item in new_sys_path: sys.path.remove(item) sys.path[:0] = new_sys_path from django.core.handlers.wsgi import WSGIHandler os.environ['DJANGO_SETTINGS_MODULE'] = '[projectname].settings' application = WSGIHandler()
give the scripts execute permissions:
chmod +x /home/[username]/djangosites/[projectname].wsgi
and exit user login with:
exit
now you will have your root propmt at the shell:
root@servername [/home/username]#
create the apache include folder for that virtualhost:
mkdir -p /usr/local/apache/conf/userdata/std/2/[username]/[domain]/ nano /usr/local/apache/conf/userdata/std/2/[username]/[domain]/django.conf
and add:
<ifmodule mod_wsgi.c> WSGIScriptAlias / /home/[username]/djangosites/[projectname].wsgi WSGIDaemonProcess [username] processes=7 threads=1 display-name=%{GROUP} WSGIProcessGroup [username] WSGIApplicationGroup %{GLOBAL} </ifmodule>
edit the virtualhost entry for that domain:
nano /usr/local/apache/conf/httpd.conf
and in that virtualhost add:
Include "/usr/local/apache/conf/userdata/std/2/[username]/[domain]/*.conf"
save & exit
test the apache configuration prior to reload:
service httpd configtest
Should say syntax OK at the end, if so reload the apache:
/scripts/restartsrv_httpd
And voila, you have your django instance up& running You can now add via User's cpanel media subdomain for django media files, and define the path to the subdomain root in setings.py media root can live inside public_html folder. You can also create additional subdomain for admin media and copy the admin media content to that subdoman. For example: admin-media.[domain]:
cp -r /home/[username]/virtualenv/lib/python2.6/site-packages/Django-1.2.1-py2.6.egg/django/contrib/admin/media/* /home/[username]/public_html/admin-media/