The IJC Digital Blog

Posted by: Matt Mansour 2 years, 8 months ago (0 comments)

After a hearing a great Gunicorn talk by Brian Riley of EdgeCast.com at the LADjango meetup I decided it was time to dive in to a modern server for Django. After getting around a few bumps I realized setting up Gunicorn with NGINX was easy. Even though I appreciate - and was blown away by - Graham Dumpleton's mod_wsgi for Apache, I feel it's time to push forward. I am glad I did and as a result, if I am unable to use Heroku on a project I will now most likely use NGINX, Gunicorn, and Postgres as the stack for some Django projects.

Gunicorn is a simple pip install. This set up assumes you are using virtualenv, that your environments are located in ~/envs, and your projects are located in ~/webapps. For the purpose of this article I will call the Django project "guni".

$ virtualenv ~/envs/guni --no-site-packages
$ cd ~/envs/guni/bin
$ source activate
(guni)$ pip install django
(guni)$ pip install gunicorn
(guni)$ cd ~/webapps
(guni)$ django-admin startproject guni

Now that we have Gunicorn and Django installed we create a simple shell script. We will invoke this script to start and monitor Gunicorn.

(guni)$ cd guni

Create a new file called guni.sh

(guni)$ sudo vim guni.sh

Copy everything between the dashed lines and configure for your project and server settings. --------------- guni.sh

#!/bin/bash
set -e
LOGFILE=/home/username/webapps/guni/logs/guni.log
LOGDIR=$(dirname $LOGFILE)
NUM_WORKERS=3
# user/group to run as
USER= username
GROUP= username
ADDRESS=127.0.0.1:8001
cd /home/username/webapps/guni
source /home/username/envs/guni/bin/activate
test -d $LOGDIR || mkdir -p $LOGDIR
exec gunicorn_django -w $NUM_WORKERS --bind=$ADDRESS \
  --user=$USER --group=$GROUP --log-level=debug \
  --log-file=$LOGFILE 2>>$LOGFILE

----------------

Test the server from bash

(guni)$ bash guni.sh

If you see nothing that's good.

Test server from gunicorn command

(guni)$ gunicorn_django --bind=127.0.0.1:8001

You should see something like the following:

2012-02-29 23:04:24 [4558] [INFO] Starting gunicorn 0.13.4
2012-02-29 23:04:24 [4558] [INFO] Listening at: http://127.0.0.1:8001 (4558)
2012-02-29 23:04:24 [4558] [INFO] Using worker: sync
2012-02-29 23:04:24 [4561] [INFO] Booting worker with pid: 4561

*Note. I had to change the port to 8001 because I already have another gunicorn server using port 8000. In guni.sh the following lines change my port:

ADDRESS=127.0.0.1:8001

and

--bind=$ADDRESS #as a parameter in the 'exec' command

Likewise

$ gunicorn_django --bind=127.0.0.1:8001

can be used to test the server on a different port - 8001 in this case.

Install and configure NGINX

$ sudo aptitude install nginx
$ sudo vim /etc/nginx/sites-enabled/default

Copy and paste the block between the dotted lines, then configure for your project

--------------- /etc/nginx/sites-enabled/default

upstream app_server_djangoapp {
    server localhost:8001 fail_timeout=0;
}

server {
    listen 80;
    server_name yourdomain.com;

    access_log  /var/log/nginx/guni-access.log;
    error_log  /var/log/nginx/guni-error.log info;

    keepalive_timeout 5;

    # path for static files
    root /home/username/webapps/guni/static;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://app_server_djangoapp;
            break;
        }
    }
}

-----------------

Restart NGINX

$ sudo /etc/init.d/nginx restart

At this point we can manually start Gunicorn with, "$ gunicorn_django --bind=127.0.0.1:8001" and see the "Welcome to your first Django page..." at yourdomain.com, if yourdomain.com pointing to your server/DNS. However, we need to set up monitoring to auto start Gunicorn during system reboots and such. I am using Ubuntu (10.10). It ships with a program for this called Upstart. Ironically, Upstart was giving me a headache, so I decided to use another program called Supervisor instead, which was easy:

Install supervisor

$ sudo apt-get install supervisor

Create and save a new supervisor configuration file for your project in the location below:

$ sudo vim /etc/supervisor/conf.d/guni.conf

Copy the block between the dotted lines and configure for your project

--------------- guni.conf

[program: guni]
directory = /home/username/webapps/guni/
user = username
command = /home/username/webapps/guni/guni.sh
stdout_logfile = /path/to/supervisor/log/file/logfile.log
stderr_logfile = /path/to/supervisor/log/file/error-logfile.log

---------------

Restart supervisor for the configuration changes to take hold

$ sudo /etc/init.d/supervisor restart

Or maybe this depending on your distro:

$ sudo supervisorctl reload

You can check that it is working with:

sudo supervisorctl status

*Check the links below if you get stuck.

Tell supervisor to monitor your project (guni)

$ supervisorctl start guni

Now if you reboot Ubuntu Gunicorn will automagically start.

I'd like to thank the following developers for their blog posts. Their work helped get me through this process relatively painlessly:

http://davidpoblador.com/run-django-apps-using-gunicorn-and-nginx/

http://senko.net/en/django-nginx-gunicorn/

http://serverfault.com/questions/211525/deploying-using-supervisor-and-gunicorn

Current rating: 5

Comments