This is a quick update to my tutorial on hosting Django Apps on Ubuntu with Nginx and uWSGI. I recently wanted to move to a mix of Python 3.4 and Python 2.7 web apps on one of my servers that was set up as described in that tutorial. Here's how to do that.
Normally, I just install uWSGI using pip. The big downside of that approach is that it only builds uWSGI for the version of Python with which you install it. So to get one emperor that can run apps (vassals) with different versions of Python, we need to compile uWSGI. Luckily it's really easy.
Here is an example of the required steps. Just run the following commands as root.
First download and extract uWSGI. Here's an example; check the website for the latest version and update the commands accordingly:
wget http://projects.unbit.it/downloads/uwsgi-22.214.171.124.tar.gz tar zxvf uwsgi-126.96.36.199.tar.gz cd uwsgi-188.8.131.52/
One thing before we compile: we need to tell uWSGI where it's going to find the various python plugins. Edit
buildconf/base.ini and set
plugin_dir = /usr/local/lib/uwsgi/ . You are now ready to compile uWSGI.
We'll compile uWSGI without Python support, then separately compile plugins for each version of Python we want to support:
make PROFILE=nolang PYTHON=python3.4 ./uwsgi --build-plugin "plugins/python python34" PYTHON=python2.7 ./uwsgi --build-plugin "plugins/python python27"
Now you could run uWSGI from this folder, but I prefer to install it:
mkdir /usr/local/lib/uwsgi/ cp python*_plugin.so /usr/local/lib/uwsgi/ cp uwsgi /usr/local/bin/uwsgi
Finally, you'll want an upstart or systemd file to boot uwsgi. Here's an upstart example (same as in my previous tutorial), which you would install as
# Emperor uWSGI script description "uWSGI Emperor" start on runlevel  stop on runlevel  exec uwsgi --die-on-term --emperor /etc/uwsgi --emperor-tyrant --logto /var/log/uwsgi.log
For each web app you want to run, create a config file in
/etc/uwsgi that's owned by the user you want that app to run under. Include the setting
plugin = python27 or
plugin = python34 to indicate which python plugin you want to use for that app.
Example of an app config file in
%n mean "the filename without extension" which makes this sort of settings file really easy to re-use):
[uwsgi] socket = /apps/%n/uwsgi/socket chmod-socket = 664 master = true processes = 2 virtualenv = /apps/%n/app/venv pythonpath = /apps/%n/app/ module = %n.wsgi pidfile2 = /apps/%n/uwsgi/pid daemonize = /apps/%n/uwsgi/log plugin = python27
You now have a shiny new uWSGI emperor, serving multiple python apps with support for python 2.7 and 3.4.