Using Gunicorn on the ActivePython AMI
by Troy Topnik

Troy Topnik, February 4, 2011
gunicorn on the ActivePython AMI

Last month we posted a screencast from Raymond Hettinger on Getting Started with the ActivePython AMI on EC2. For this follow-up post, Mike Ivanov walked me through how to swap the default Apache web server for Gunicorn (aka Green Unicorn, a Python WSGI web server) which is a popular replacement for Django environments.

This tutorial continues on from the Building a Python-centric WebServer in the Cloud tutorial, but to make it more broadly useful we're going to edit the configuration files in place on the server, rather than using Fabric for deployment as mentioned in the tutorial. Using fab is ultimately more flexible and powerful, but editing files on the server works too.

1) Install Gunicorn

This part is easy using PyPM. Log in to your EC2 instance using SSH and run the following command:

/opt/ActivePython-2.6/bin/pypm install gunicorn

2) Change the config files

We'll start by creating a Gunicorn configuration file which will serve the same purpose as the demosite.wsgi configuration file in the Apache setup. Substitute vim with your favorite shell editor.

sudo vim /var/www/demosite/etc/

Paste in this:

import os

os.environ['PRODUCTION'] = 'TRUE'
os.environ['DEMOSITE_DB_HOST'] = open('/var/www/demosite/etc/dbhost').read().strip()

def num_cpus():
    if not hasattr(os, "sysconf"):
        raise RuntimeError("No sysconf detected.")
    return os.sysconf("SC_NPROCESSORS_CONF")
bind = ""
workers = num_cups() * 2
max_requests = 1000
preload = True
pid = "/var/run/"

Nothing special here. This config would be almost exactly the same for another project. Note that there's no mention of our project ("demosite") here. That's because we're not going to run Gunicorn by itself, it's just a Python script running a WSGI server. To make a system daemon out of it, we need to use an external tool. We'll use supervisor, which is a convenient process control system for UNIX-like systems. It's installed with ActivePython on the AMI.

Create a supervisor config file:

sudo vim /var/www/demosite/etc/supervisor.conf

Paste in this configuration to tie the pieces together:

command=/var/www/demosite/env/bin/gunicorn_django -c /var/www/demosite/etc/

The command= setting tells supervisor to run the gunicorn_django launcher script with our new configuration file. The directory= line tells supervisor where the site is. If you've been using fab it would be something like /var/www/demosite/releases/current instead.

Note the user and group. These are the same as Apache's default user/group combination for WSGI processes. This could be specified in the gunicorn config, but is easier to do here.

To get supervisor to bring up demosite at boot, we need a symlink in supervisors conf.d directory:

sudo ln -s /var/www/demosite/etc/supervisor.conf /etc/supervisor/conf.d/demosite.conf

Again, if you're using fab the path will have 'releases/current' in it.

4) Try it out!

Since Apache is already running by default, we should stop that service before starting up Gunicorn using supervisorctl:

sudo service apache2 stop
sudo supervisorctl demosite start

We can do a quick check using curl to make sure we can connect directly to Gunicorn:

curl localhost:8080

On the ActivePython AMI, Nginx is sitting in front of Gunicorn for better performance and to protect against denial of service attacks. It forwards our demosite on to port 80 where it can be seen by the outside world.

So now we have a running Django stack that uses a server with native support for WSGI and Django with a much more Pythonic approach to configuration.

Subscribe to ActiveState Blogs by Email

Share this post:

Category: python
About the Author: RSS

As ActiveState's Technical Product Manager for Stackato, Troy Topnik is responsible for defining and prioritizing the product roadmap to build the best cloud platform for deploying applications. Since joining ActiveState in 2001, he has held roles in Technical Support, Training, and Technical Writing. He believes in documentation-driven development as a pragmatic path to a better user experience.