This week (tonight) I moved my major sites (this site, my wife’s site and my brothers site) over to Gunicorn from Mod_wsgi. I initially thought it was going to be an incredibly different process, but I’m here to show that it can be done in one night and it isn’t nearly as hard as I thought. I wanted to document and outline the process in case anyone else wanted to make the transition.
First of all I started with upgrading to Django 1.4 and using Gunicorn 0.17.2. Gunicorn provides an easy django management command to run the Gunicorn server. To run Gunicorn you’ll need to proxy it through another HTTP server such as Nginx. Luckily Webfaction makes this really easy and when you create a custom application in the control panel you are given a port number that is automatically proxied through Nginx. The next thing you are going to need is to setup supervisord. Supervisord will monitor your Gunicorn workers and restart those that fail, keeping your site up. You’ll want supervisord in and when you choose to setup Celery as well. Installing Supervisord is easy, simply:
pip install supervisor
I installed supervisord at the system level and not in a virtualenv on purpose. Doing so makes it available to more than one site (assuming you do this) and makes it much easier to configure. In order to use supervisord you’ll need to configure it to pick up the different processes. Supervisord looks for configs in /etc/supervisord.conf and ~/etc/supervisord.conf. Below is my configuration.
[unix_http_server] file=/home/dstegelman/tmp/supervisor.sock [supervisord] logfile=/home/dstegelman/supervisor/logs/supervisord.log logfile_maxbytes=50MB logfile_backups=10 loglevel=info pidfile=/home/dstegelman/etc/supervisord.pid [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl=unix:///home/dstegelman/tmp/supervisor.sock [include] files = /home/dstegelman/projects/derek-stegelman-com/conf/supervisor.ini /home/dstegelman/projects/blog-stegelman-com/conf/supervisor.ini /home/dstegelman/projects/urban-paint-crm/conf/supervisor.ini
To install gunicorn just pip install it in your virtualenv: As with any other app, make sure to add it to your requirements file.
pip install gunicorn
After installing add it to your django installed apps and you’ll have access to the run_gunicorn command.
######Back to Supervisord
As you can see in my supervisor config I am including several files that have their own config. Doing so bundles the configs of the apps to the app itself and keeps it in version control. Also you’ll want to make sure all the directories listed above actually exist, they will not be created for you at run time. (/home/dstegelman/supervisor/logs/, etc). Once you have this setup you can go ahead and boot supervisord.
######supervisord Doing so will load your various supervisor configs located in your projects. A sample one is provided below for one of my projects:
[program:derek_stegelman_com] command=/srv/www/virtualenvs/derek-stegelman-com/bin/python /srv/www/projects/derek-stegelman-com/manage.py run_gunicorn -c=/srv/www/projects/derek-stegelman-com/conf/gunicorn.conf.py --settings=settings.production directory=/srv/www/projects/derek-stegelman-com user=dstegelman autostart=true autorestart=true redirect_stderr=True
This goes ahead and activates my virtualenv and then runs the gunicorn server on the port that Webfaction initially provided me. These settings are located in the guncorn config file that I have specified. I’ve configured some other things like settings and max requests here that you can change as well.
Every time you make a change to a supervisor.ini file you need to restart not just the single process, but supervisord itself. In order to do so run:
######supervisord This will reload all processes including the supervisord daemon itself. At this point you’ll need to connect your webfaction app up to your domain with a website and you should be good to go.
Restarting and Reloading supervisord Gunicorn Web Site Supervisord Site Configure Supervisord ######Edit
I had to add an ‘exec’ statement before the Gunicorn line to allow supervisor to actually start and stop the server processes.