--- Setting up Nginx + uWSGI Emperor to host Python applications on Ubuntu 12.04 - Collabspot

Setting up Nginx + uWSGI Emperor to host Python applications on Ubuntu 12.04

14 Aug 2012 by


This is the first of many posts on how our server is set up to serve Python web applications and others. For this post, we'll focus on setting up Nginx and uWSGI and getting a bare-bones Django application running and served by Nginx.

Installing Nginx

Nginx is available in the Ubuntu software repositories, so installing it is pretty simple.

$ apt-get install nginx

Test your installation by starting Nginx:

$ /etc/init.d/nginx start

You should see a message along the lines of "starting nginx".

Check out Linode's impressive library for a more thorough walkthrough on installing Nginx.

Installing uWSGI

uWSGI is available in the Ubuntu repositories as well, and also on PyPI. It's up to you which method you prefer.

$ apt-get install uwsgi
# or
$ pip install uwsgi
Setting up our Django project

First thing we need to do is prepare some folders on where our project will live. We use the structure below for our projects:

$ mkdir /var/www/example.com
$ cd /var/www/example.com
$ mkdir venv conf src logs


/var/www/ `- example.com/ |- venv/ |- conf/ | |- nginx.conf (include in main nginx.conf) | `- uwsgi.ini |- src/ | `- example/ (django-admin.py startproject example) `- logs/ |- access.log (nginx access log) `- error.log (nginx error log)
venv/

This is where the virtual environment lives.

$ virtualenv /var/www/example.com/venv
$ source /var/www/example.com/venv/bin/activate
(venv)$ pip install django
src/

This is where the project's source code lives.

$ mkdir /var/www/example.com/src
$ cd /var/www/example.com/src
(venv)$ django-admin.py startproject example
conf/

This is where configuration files for Nginx and uWSGI are stored.

conf/uwsgi.ini

[uwsgi]
# variables
projectname = example
projectdomain = example.com
base = /var/www/example.com
# config
protocol = uwsgi
venv = %(base)/venv
pythonpath = %(base)/src/%(projectname)
module = %(projectname).wsgi
socket = /tmp/%(projectdomain).sock
logto = %(base)/logs/uwsgi.log 


The .ini template above only works for Django >= 1.4. For Django < 1.4, check out uWSGI's wiki for a template.

conf/nginx.conf

server {
  listen 92;
  server_name example.com www.example.com;
  root /var/www/example.com/src/example;
  access_log /var/www/example.com/logs/access.log;
  error_log /var/www/example.com/logs/error.log;


location / { include uwsgi_params; uwsgi_pass unix:///tmp/example.com.sock; } }

You'll need to modify your main nginx.conf to include the project's nginx.conf. Assuming Nginx was installed in /etc/nginx/, the main nginx.conf is /etc/nginx/conf/nginx.conf:

user    www-data;
# ...
http {
  # ...
  include /var/www/*/conf/nginx.conf;   
  # ...
}

That include statement will include any nginx.conf files in all projects following the structure outlined earlier.

We can now test if our application is being served on port 92 as specified in the nginx.conf.

# restart nginx
$ /etc/init.d/nginx restart
# run uWSGI pointing to our project's .ini file
# you can comment out the `logto` setting in
# uwsgi.ini to see log messages in the terminal
$ uwsgi --ini /var/www/example.com/conf/uwsgi.ini

Now open up a new terminal to your server and run:

$ curl http://localhost:92

If everything goes well, it should output the "Congratulations!" page from Django.

If not, check your conf files and/or the directories. Depending on your permissions, you might need to run uwsgi with sudo to allow uWSGI to create the /tmp/*.sock and /var/log/uwsgi/*.log files.

uWSGI Emperor

Emperor is a feature that monitors multiple uWSGI applications.

Let's try running the app via Emperor:

$ uwsgi --emperor "/var/www/*/conf/uwsgi.ini"

What this does is it runs uWSGI's Emperor mode looking for any uwsgi.ini files for all apps living in /var/www/ and starting/stopping/restarting them as needed. Any new additions will be automatically started, no need to restart Emperor itself. If an existing uwsgi.ini is modified, it is also automatically restarted.

Supervisord

We're almost done. We just need a way to manage the uWSGI Emperor process. We use Supervisord to do this.

supervisord.conf

[program:uwsgi-emperor]
command=/usr/local/bin/uwsgi --emperor "/var/www/*/conf/uwsgi.ini" --die-on-term --master --uid www-data --gid www-data --logto /var/log/uwsgi/emperor.log
autostart=true
autorestart=true
redirect_stderr=true

Don't forget to create the /var/log/uwsgi/ folder for the uWSGI logs. Again, depending on your permissions, you might need to change its user:group to www-data.

We use this init script to manage Supervisord.

Let's test everything again.

$ /etc/init.d/nginx restart
$ supervisord
$ curl localhost:92


If you're having trouble or if some part isn't clear or incorrect, don't hesitate to drop me an email or leave a comment below.



update: Changing so nginx run as www-data.



blog comments powered by Disqus