Notes on Serving Django Apps with uWSGI

I've been playing around with deploying/migrating some Django projects to a Rackspace Cloud Server with Nginx and uWSGI. These are my notes on getting started with uWSGI.

It should be noted that I am a developer and not a sys admin. Moreover, I am still learning and experimenting with uWSGI. This setup is being tested and tweaked on a few small projects that only handle a few thousand visitors per day. Rapid scalability and heavy loads are not a concern for these projects.

Comments from "real" system administrators would be appreciated.

My Setup

This setup uses...

  • Ubuntu LTS
  • Nginx >= 0.8.4
  • Django >= 1.4

Installing uWSGI

I installed uWSGI using pip, however, I believe it is included in the Ubuntu repositories starting with Ubuntu 12.04.

sudo pip install uWSGI

Emperor Upstart Script

Since I am serving several Django websites on one server, I created an Upstart script to run the uWSGI Emperor. This way, uWSGI will watch the /etc/uwsgi/apps-enabled directory for new configuration files and automatically spawn instances on demand. I simply symlink a project-specific uWSGI configuration file to /etc/uwsgi/apps-enabled.

The following Upstart script is created at /etc/init/uwsgi.conf

description     "uWSGI Emperor"

start on (filesystem and net-device-up IFACE=lo)
stop on runlevel [!2345]

respawn

env LOGTO=/var/log/uwsgi.log
env BINPATH=/usr/local/bin/uwsgi

exec $BINPATH --emperor /etc/uwsgi/apps-enabled --logto $LOGTO

Force a reload of the configuration directory.

sudo initctl reload

Start the uWSGI Emperor.

sudo service uwsgi start

At this point, the uWSGI emperor process can be seen running with top -c. If not, check the error log at /var/log/uwsgi.log.

uWSGI Configuration File

I layout my projects such that project-level server configuration files are version controlled, every project has it's own virtual environment, and each project has it's own server logs.

mywebsite.com/
    config/     <-- server configs
    logs/       <-- project-level server logs
    mywebsite/  <-- Django 1.4+ project
    venv/       <-- virtual environment

The server configuration files in the config/ directory are symlinked into the filesystem to "enable" a site.

The uWSGI configuration file has a ton of configuration options and I still have a lot of experimenting to do. But, the following configuration seems to get me up and running. It is created in my project's config/ directory and then symlinked to /etc/uwsgi/apps-enabled/mywebsite.ini (where "mywebsite" is the name of the project).

[uwsgi]
; define variables to use in this script
project = mywebsite
base_dir = /home/micah/www/%(project).com

; don't forget user and group have write access to MEDIA_ROOT
uid = www-data
gid = www-data

; process name for easy identification in top
procname = %(project)

; number of worker processes
processes = 2

; project-level logging to the logs/ folder
logto = %(base_dir)/logs/uwsgi.log

; django >= 1.4 project
chdir = %(base_dir)/%(project)
module = %(project).wsgi

; add virtual environment to path
virtualenv = %(base_dir)/venv

; unix socket (referenced in nginx configuration)
socket = /var/run/%(project).sock
chmod-socket = 666

; run master process as root
master = true
master-as-root = true

Once this file is symlinked to /etc/uwsgi/apps-enabled/mywebsite.ini, the uWSGI Emperor should pick it up and spawn new processes. In this case, there would be 3 new processes. One master process running as root and 2 worker processes running as www-data. They would show up in top -c as "mywebsite".

Nginx Configuration

While my Nginx configurations are quite a bit more complicated than this, the following simplification shows the bits that are relevant to uWSGI.

server {
    listen       80;
    server_name  mywebsite.com;

    root        /home/micah/www/mywebsite.com/;
    access_log  /home/micah/www/mywebsite.com/logs/nginx_access.log;
    error_log   /home/micah/www/mywebsite.com/logs/nginx_error.log;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/var/run/mywebsite.sock;
    }
}

Once the nginx configuration is in place the Nginx web server needs to be restarted.

Did you enjoy Notes on Serving Django Apps with uWSGI? If you would like to help support my work, A donation of a buck or two would be very much appreciated.
blog comments powered by Disqus
Linux Servers on the Cloud IN MINUTES