Deploying CherryPy on Apache 2 using mod_proxy

  2007-08-16


Background

I’ve been trying to move away from PHP to Python for web applications. I tried Django and TurboGears, but I settled upon the more basic CherryPy framework. It helped that my friend Christian is active in the CherryPy community and promised to answer all of my stupid questions (thanks Christian!).

Regardless of which framework I had chosen though, they all have a significant architectural difference from PHP:

  • PHP is a scripting language.
  • Django, TurboGears, CherryPy, etc. are application servers.

Technically Python is a scripting language and PHP+Apache could be called an application server, so I should explain:

  • PHP web applications are executed from start to finish for each web request.
  • The Python frameworks all run as a daemon and requests are processed based on object and method mappings.

Still probably a gross oversimplification, but for the sake of brevity lets move on!

The reason I mention these fundamental differences is because they completely change how you deploy your web applications. PHP scripts can be FTPed (via SSH/SSL/TLS of course!) to a web accessible directory and instantly accessed. Python web applications must be started and somehow integrated with your existing web server (Apache 2 in my case).

The Problem

So how do you deploy CherryPy applications and have them play nice with Apache 2?

One Solution: Using mod_proxy

Warning: These instructions are for Debian Etch, but the principles should be fairly universal.

Example domain: www.example.com

Example CherryPy URL: http://www.example.com/webapp/

Example CherryPy Root Object: WebApp()

Example CherryPy Configuration File: webapp.config

  1. Install Apache 2 (if you don’t use PHP, feel free to choose a MPM other than prefork) and Python
  2. Install python-setuptools if you haven’t already:

    sudo apt-get install python-setuptools

  3. Install CherryPy via _easyinstall to get the latest stable version:

    sudo easy_install cherrypy

  4. Edit your CherryPy applications’ config file (webapp.config in this example) to include the following lines:

    server.socket_port = 6464<br /> server.socket_host = "127.0.0.1"

  5. To start your web application you should have a line similar to:

    cherrypy.quickstart(WebApp(), ‘/webapp’, ‘webapp.config’)

  6. Start your application as a background process. I usually use a command like this:

    python start-webapp.py > stdout.log &

  7. If you have lynx or links installed you can test your web application:

    lynx http://127.0.01:6464/webapp/

  8. Enable mod_proxy for Apache 2:

    sudo a2enmod proxy_http

  9. Add the following to the Apache virtual host configuration for www.example.com (for example: /etc/apache2/sites-enabled/000-default or /etc/apache2/sites-enabled/www.example.com):

    ProxyPreserveHost on<br /> <Proxy *><br />   Order allow,deny<br />   Allow from all<br /> </Proxy><br /> ProxyPass /webapp/ http://127.0.0.1:6464/webapp/<br /> ProxyPassReverse /webapp/ http://127.0.0.1:6464/webapp/

  10. Restart Apache 2 using the following command:

    sudo /etc/init.d/apache2 force-reload

Go to http://www.example.com/webapp to see if it works!

**Caveats and Tips

**

  • Be careful using absolute URLs (especially in redirects!) in your web application.
  • To make sure your web application always starts at boot, add this line to your crontab:

    @reboot /usr/bin/python /path/to/start-webapp.py > /path/to/stdout.log &

Other Solutions

Using mod_proxy is neither the only way to deploy CherryPy web applications nor the best for all deployment scenarios. Once I have a bit more experience I’d love to post a side-by-side comparison, but for now your probably best off reading CherryPy’s wiki article on the subject.