Deploying Django behind nginx with uwsgi and virtualenv

Written by Johannes on November 27, 2012 Categories: Django, Python, uwsgi

Your ads will be inserted here by

Easy AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

UPDATE (2013-06-10): On a more recent deployment I got errors of the “Python application not found”-kind. It took me a while to figure it out, apparently the current Django stable (1.5 at the point of writing) requires the settings module to be passed to the uwsgi process environment variables. END OF UPDATE

We use nginx to deploy Django on our staging-server and keep Django running in a virtualenv. This allows us to easily separate different projects or release versions of our Software. We use CentOS 6-systems for deployment.

This guide won’t cover deployment on SE-Linux, you have to figure that out for yourself or disable SE-Linux if your application isn’t security critical.

You won’t find nginx in the official CentOS 6 repositories, but there is an official repository provided by the nginx-developers. Add the following file to your /etc/yum.repos.d/ directory:

[root@host ~]$ cat /etc/yum.repos.d/nginx.repo 
[nginx]
name=nginx repo
# base url for 64 bit cent os
baseurl=http://nginx.org/packages/centos/6/x86_64/
# base url for 32 bit cent os
# baseurl=http://nginx.org/packages/centos/6/i686/
gpgcheck=0
enabled=1

and install nginx.

Now add a new user home directory to run your django instance in, and add the nginx-User to the corresponding group:

# create user
[root@host ~]$ useradd -m projectname
# give nginx group level access to user directory
[root@host ~]$ usermod -a -G projectname nginx
# make home directory group readable and executable
[root@host ~]$ chmod g+rx /home/projectname

With that work done, let’s install Django. First install virtualenv, if you haven’t already done so.

# install setuptools if you don't have them installed yet
[root@host ~]$ yum install python-setuptools
[root@host ~]$ easy_install virtualenv

Now switch to your project user, create and activate a virtual environment.

[root@host ~]$ su projectname
# switch to home dir if necessary
[projectname@host root]$ cd
[projectname@host ~]$ virtualenv env
[projectname@host ~]$ source env/bin/activate

You can now install Django into the virtual enviroment with pip. We use git to obtain the latest source code, but you can also use the tarballs provided by the Django project or the internal pip installer.

Your ads will be inserted here by

Easy AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

# obtain latest stable code via git, use -b to check out relevant branch
[(env)projectname@host ~]$ git clone git://github.com/django/django.git -b stable/1.5.x django
# install code from repository with pip
[(env)projectname@host ~]$ pip -e django

pip needs to compile some sources to install uwsgi, so you need development tools (gcc, make, …), libxml2 header and python headers.

# open root shell
[root@host ~]$ yum groupinstall "Development Tools"
[root@host ~]$ yum install python-devel libxml2-devel

Now install uwsgi.

# install uwsgi in virtual environment
[(env)projectname@host ~]$ pip install uwsgi

Copy your Django project code to the home directory and create an uwsgi.ini file.

(env)[project@host ~]$ cat uwsgi.ini 
[uwsgi]
# path to where you put your project code
chdir=/home/project/project
 
# python path to the wsgi module, check if you have one
module=project.wsgi:application
 
# this switch tells uwsgi to spawn a master process,
# that will dynamically spawn new child processes for
# server requests
master=True
# uwsgi stores the pid of your master process here
pidfile=/home/project/master.pid
vacuum=True
# path to your virtual environment
home=/home/project/env/
# path to log file
daemonize=/home/project/log
# this is where you need to point nginx to,
# if you chose to put this in project home make
# sure the home dir is readable and executable by
# nginx
socket=/tmp/uwsgi.sock
 
### SEE UPDATE NOTICE FOR THIS ONE
env = DJANGO_SETTINGS_MODULE=project.settings

Now you need to point nginx to the uwsgi socket:

# make sure /etc/nginx/conf.d/default.conf gets loaded in /etc/nginx/nginx.conf
# in the http section
[root@host ~]$ cat /etc/nginx/conf.d/default.conf 
server {
    listen       80;
    server_name  yourserver.example.org;
 
    location / {
        uwsgi_pass unix:///tmp/uwsgi.sock;
        include uwsgi_params;
    }
 
    # static code has to reside in /home/project/project/static
    # for this to work
    location /static {
        root /home/project/project;
    }
 
    error_page  404              /404.html;
 
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Start the uwsgi process and restart your nginx server.

# start uwsgi from virtual environment
(env)[project@host ~]$ uwsgi --ini uwsgi.ini
 
# restart nginx as root
[root@host ~]$ service nginx restart

You can kill the uwsgi master process and its child processes by issuing

[project@host ~]$ uwsgi --stop master.pid
No Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre user="" computer="" escaped="">