Dreamhost is a pretty decent provider for people with lots of small websites. I didn’t expect them to have, say, Python 3 (although I’d love to), but I was surprised to find their official support is just for 2.4!
There are instructions for custom builds, but they are not much supportive (“If you are positive that you need to install Python, reconsider”), and a few unofficial ones. Here are the steps I used – try them at your own risk, since I can’t give any guarantees other than the fact that they worked for me (hint: create a new subdomain with its own user and try that there first.)
(These instructions might also work for Python 3.0 – just replace the version numbers accordingly. I did not test that (yet), but if you do, please let me know.)
The first step is to download, build and install the desired Python version (2.6.5). To do that, enable ssh access to that domain (via Dreamhost Panel), ssh to it, then issue the commands below:
mkdir work cd work wget http://python.org/ftp/python/2.6.5/Python-2.6.5.tgz tar -xzvf Python-2.6.5.tgz cd Python-2.6.5 ./configure --prefix=$HOME/local make make install
You can do all this because the --prefix
ensures files will be inside your home dir (but outside the yourdomain.com
dir, so they will be private), under ~/local/bin
, ~/local/lib
, and so on.
Now prepend the ~/local/bin
directory to your path (to force your shell to “see” this Python install before Dreamhost’s) by appending the following lines to the .bash_profile
file located on your home directory (using vi
, pico
or other editor):
# Added for custom-built python 2.6 PATH=$HOME/local/bin:$PATH export PATH
Logoff and logon, and voila! You have a decent Python:
$ python Python 2.6.5 (r265:79063, Apr 8 2010, 02:30:51) [GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
Most add-ons will find your site-packages and related directories automatically. Some configure
scripts for makefiles may not, but adding a --prefix=${HOME}/.local
parameter (or something like that, check the script’s help if that happens) should solve the issue.
Django can be installed onto this Python setup by following the standard instructions. In my case:
cd ~/work wget http://www.djangoproject.com/download/1.1.1/tarball/ tar xvzf Django-1.1.1.tar.gz cd Django-1.1.1 python setup.py install
I also had to add MySQL for Python:
cd ~/work wget http://downloads.sourceforge.net/project/mysql-python/mysql-python-test/1.2.3c1/MySQL-python-1.2.3c1.tar.gz?use_mirror=ufpr tar -xvzf MySQL-python-1.2.3c1.tar.gz cd MySQL-python-1.2.3c1 python setup.py build python setup.py install
For most libraries, however, you will prefer easy_install
, which is part of setuptools. However, if you type easy_install
now, it will use the Python 2.4 version (to which you can’t add libraries anyway). Let’s fix it with:
cd ~/work wget http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c11-py2.6.egg#md5=bfa92100bd772d5a213eedd356d64086 bash setuptools-0.6c11-py2.6.egg
After that, easy_install
should work – if not, try easy_install-2.6
. One caveat is that libraries that build against native binaries must have access to them on the correct places. My issue was with lxml, but I solved it with these instructions (only changing .local
to local
).
That should allow you to add everything you need until your app works fine – that is, if you can enter python manage.py shell
under the Django project dir, import some stuff, run your unit tests (you have coded tests, right?), etc.
Unfortunately, Dreamhost’s web server (Apache) will still use the old Python – and you need to change that to put your app online. I guess there is some FastCGI trickery for that, but a cleaner way (in my humble opinion) is to use Passenger (aka “mod_rails”, which Dreamhost supports due to the popularity of Ruby on Rails) with Python Web Server Gateway Interface (WSGI).
Dreamhost’s documentation os Passenger WSGI has a useful bootstrap script (at least if you did not start your Django project already), but let’s assume you already have one (if not, you should really play a little bit beforehand.)
In this process, we’ll separate “static” content (in fact, all non-Python stuff, including PHP/Perl pages) from the Python/Django files. Return to your domain’s configuration on Dreamhost Panel and change the “Web Directory” from "<home dir>/yourdomain.com"
to "<home dir>/yourdomain.com/public"
(i.e., append a “public” sub-directory), then tick the “Passenger (Ruby/Python apps only)” checkbox.
After that, wait until the public
directory shows up and move your existing static files (if any) to it. If you haven’t already uploaded your Django project dir, put it under yourdomain.com
, that is, side-by-side with public
.
You should now have a directory structure like this: *
- /home/yourusername/
- local/
- bin/
- include/
- lib/
- share/
- yourdomain.com/
- public/
- yourDjangoProjectDirectory/
- logs/
- work/
- local/
</em>
Create a passenger_wsgi.py
file on the “yourdomain.com
” directory, with the lines below (replace /home/XXXXXX
with your real home and YYYYYY
with your Django project directory):
import sys, os INTERP = "/home/XXXXXX/local/bin/python" if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv) sys.path.append(os.getcwd()) os.environ['DJANGO_SETTINGS_MODULE'] = "YYYYYY.settings" import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
The magic here is that this file will be detected by Passenger and will be used by it whenever an URL that is not an static file under public is called. It will first switch the environment from the default Python (which we can’t change anyway) to our custom-built one, then build a Django environment (the application
variable) which will handle valid URLs.
The beauty of this setup is that non-Python files (static content and stuff such as PHP) located inside public
will be served directly by Apache, and your Python stuff will reside outside – Django’s URL dispatcher will control access, avoiding nasty accidents with leftover files.
After everything is set up, you can remove the ~/work
directory, and have fun with your (cheaply) hosted Python application!
Comments
Elena
Thank you, thank you, thank you! This wonderful documentation saved me :)
digitalpbk
Awesome just what i was looking for
Marcin
Thanks for this - in particular, the explanation of how static content is served seems to be missing from the dreamhost docs.