Webfaction + Virtualenv - How To

Note that while this post is oldish the process below still works well as of today: 3/26/2014

This post is going to quickly go over how I set up Django based sites quickly and easily on Webfaction using Virtualenv’s. First things first, log into your Webfaction server via SSH shell (Terminal or Putty.) Note that I use commands to use Python 2.7. Change the -2.7 to whatever version you need or prefer as necessary.

Install virtualenv

easy_install-2.7 virtualenv

Install PIP. My server didn’t have it installed yet and then add virtualenvwrapper which just makes it easier to work with virtualenv’s.

easy_install-2.7 pip
pip2.7 install virtualenvwrapper

Make a directory to house your virtualenv’s. You can use whatever you want in place of .virtualenvs/

 mkdir ~/.virtualenvs

Edit the shell profile to add our virtualenv directory and set up the environment. I use nano but you can use whatever Linux editor floats your boat.

 nano ~/.bash_profile

Add these lines to the .bash_profile file, save it and quit or reload terminal for your changes to take effect.

export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_TMPDIR=$HOME/.virtualenvs/tmp
export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python2.7
source $HOME/bin/virtualenvwrapper.sh
export PIP_VIRTUALENV_BASE=$WORKON_HOME
export PIP_RESPECT_VIRTUALENV=true

Create a virtualenv. The code below will create a virtualenv named “demo”, you should name yours a name that you actually like.

mkvirtualenv demo --no-site-packages --distribute 

Now when you log back in or reset your shell you should be able to see your new virtualenv by typing workon demo which will activate your virtualenv. You’ll know its active because your command prompt will now have a prefix of your environment name. Something like this:

(demo)[myaccount@web12 ~]$

Once you have activated your virtualenv you can install the version of Django and any other Python modules and they will be installed in your virtualenv. For instance to set up Mezzanine you would just do this:

pip2.7 install -U mezzanine

Now log into your Webfaction control panel at my.webfaction.com and create a new application that will hold your Apache instance for your new sites running off your virtualenv. The version of Django you select won’t matter so just select the latest version. It won’t matter because the Django instance in our virtualenv is going to be used when our virtualenv is activated.

For this tutorial I’m going to name the application “demo” just like my virtualenv. You need to change the name “demo” in the example httpd.conf file below to the name of the application you just created. Also, a word about project setup. My projects are a folder with settings.py, urls.py etc from Django directly inside it and I’m placing the wsgi script directly inside that folder as well. If you’re projects are structured differently then you’ll need to change the paths to these files as needed.

In your SSH shell connection change directories to your new application and git clone your project to your server. Or add it via SVN or whatever version control you are using. What? You’re not using version control. Uhh, its 2012! Well, you could just FTP it up as well if you must.

Edit your new Apache configuration file to add your first site but first make a backup in case you totally mess this up.

cp ~/webapps/demo/apache2/conf/httpd.conf httpd_backup.conf
nano ~/webapps/demo/apache2/conf/httpd.conf 

You’re Apache configuration should have the elements below. Make sure that you take notice of the port Apache is running on, its the part at the end of the NameVirtualHost IP: in this case I have just used 12345. Change that to the same one that is there when you first open the file.

ServerRoot "/home/ACCOUNT_NAME/webapps/demo/apache2"

LoadModule dir_module        modules/mod_dir.so
LoadModule env_module        modules/mod_env.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module       modules/mod_mime.so
LoadModule rewrite_module    modules/mod_rewrite.so
LoadModule setenvif_module   modules/mod_setenvif.so
LoadModule wsgi_module       modules/mod_wsgi.so

LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" combined
CustomLog /home/ACCOUNT_NAME/logs/user/access_demo.log combined
ErrorLog /home/ACCOUNT_NAME/logs/user/error_demo.log
KeepAlive Off
Listen 12345
MaxSpareThreads 3
MinSpareThreads 1
ServerLimit 1
SetEnvIf X-Forwarded-SSL on HTTPS=1
ThreadsPerChild 5
HostnameLookups Off
WSGIRestrictStdout Off

NameVirtualHost 127.0.0.1:12345

# Begin site configuration
<VirtualHost 127.0.0.1:12345>
    WSGIScriptAlias / /home/ACCOUNT_NAME/webapps/demo/mysite/mysite.wsgi
    ServerName mysite.com
    ServerAlias www.mysite.com
    ServerAdmin web@mysite.com
    ErrorLog "/home/ACCOUNT_NAME/logs/user/mysite.log"
</VirtualHost>

We pointed to a WSGI config file above in our Apache config and thats where the fun begins. You’ll notice that we’re activating our virtualenv and setting up the project directories in this file. The second part of the sys.path portion adds an “apps” directory in my project which is where I add my customizations for each project. Again, if your projects are set up differently you’ll need to change the path or you can eliminate it entirely.

import os, sys, site

site.addsitedir('/home/ACCOUNT_NAME/.virtualenvs/demo/lib/python2.7/site-packages')

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

activate_this = os.path.expanduser("~/.virtualenvs/demo/bin/activate_this.py")
execfile(activate_this, dict(__file__=activate_this))

# Calculate the path based on the location of the WSGI script
project = '/home/ACCOUNT_NAME/webapps/demo/mysite/'
workspace = os.path.dirname(project)
sys.path.append(workspace)

sys.path = ['/home/ACCOUNT_NAME/webapps/demo/mysite', '/home/ACCOUNT_NAME/webapps/demo/mysite/apps', '/home/ACCOUNT_NAME/webapps/demo'] + sys.path

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

When you’re ready simply do this to restart Apache.

~/webapps/demo/apache2/bin/restart

Then when you set up the website via the Webfaction control panel point the site to serve from the Django app you created above. Then create a symbolic link that links to your static media, reset Apache and Bob’s your uncle.

There are a couple of things to keep in mind when setting up new environments. If you use Postgres then you need to install psycopg2 in each new environment you set up. Likewise PIL or other components that would normally come from the Webfaction global server installation.

Please let me know if there are any sticking points or questions in the comments. Thanks!

comments powered by Disqus