October 27th, 2012

Massive Python hosting with uWSGI: Preparation

Tutorial for: uWSGI


Since I just completed my server migration, I combined 2 servers into a single server and used uWSGI to glue it all together. This tutorial explains how to get up and running with Django, however it can be applied to other frameworks which support WSGI with little to no effort.

This tutorial will be split into several parts, although all the parts will be published on the same day for your convenience. This first part will focus on the preparation of the server being used. It will require an already configured and ready to go Linux server. The distribution does not matter, as long as you can compile the latest versions of both Django and uWSGI. Please refer to the links for these packages.

Firstly, go ahead and compile Nginx and uWSGI. Once you have these happily installed on your server, proceed to your Nginx configuration directory located under /etc/nginx. Here we will create a few configuration files which we will use in the preparation of this hosting solution. Create a file in this directory called uwsgi_params, we will use this to store the parameters required for uWSGI to interface with nginx:

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO		$document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

uwsgi_param  UWSGI_FASTROUTER_KEY	$host;
uwsgi_pass   unix://srv/run/fastrouter.sock;

With this file created, lets update the sites-available/default virtualhost file to be the following:

server {

	listen   80; ## listen for ipv4

	server_name  localhost;

	access_log  /var/log/nginx/$host.access.log;

	location / {
		include		uwsgi_params;

	location /s/ {
		alias	/srv/static/$host/;

	location /m/ {
		alias	/srv/media/$host/;

	location /media/ {
		root	/opt/django12-env/lib/python2.6/site-packages/django/contrib/admin/;

The final location is there for backwards compatibility for older Django 1.2 apps. There are still some people who depend on Django 1.2, as the third party apps have not yet upgraded their code to be 1.3 compatible. The other location constructs should be fairly straightforward.

With the nginx configuration out of the way, let's proceed to creating the directory tree which will host the various Python applications. This directory structure is for your reference, I would advise you to change it to suit your particular requirements. This structure is in no way set in stone. First enter the /srv directory, and use the following commands to create the structure needed:

# mkdir apps media run sites static
# chown someuser:someuser *

Choose a user whom which you will run uWSGI as, or which user will manage the various Python applications. With this done, login into the user you choose and write this script which will start the uWSGI process:


kill `cat /srv/run/uwsgi.pid`
rm /srv/run/*
rm uwsgi.log

uwsgi --master --emperor /srv/sites --fastrouter /srv/run/fastrouter.sock --fastrouter-subscription-server --chmod-socket --pidfile /srv/run/uwsgi.pid --daemonize uwsgi.log

This file is a reference on where to begin on configuring your uWSGI master process. This process doesn't need anything too fancy, it is the other processes which are running your actual applications which need to be more fancier. You can go ahead and start the uWSGI process now. When you visit any domain pointing to this server, you will see a Gateway error message. This is normal, as we have yet to configure any applications. The next part of this tutorial will explain how to do this with Django.

Python Powered | © 2012-2014 Kevin Veroneau