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

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. About the author John Louis Del Rosario Developer. Gamer. Reader. Related Posts Creating PayPal IPN Handlers with Tornado Creating PayPal IPN Handlers with Tornado July 17, 2012 Popular Posts Setting up Nginx + uWSGI Emperor to host Python applications on Ubuntu 12.04 Setting up Nginx + uWSGI Emperor to host Python applications on Ubuntu 12.04 August 14, 2012 Scheduled Reports with CRON for App Engine Scheduled Reports with CRON for App Engine July 24, 2012 CollabSpot Boards Update (v120427) CollabSpot Boards Update (v120427) April 27, 2012 ← CollabSpot Boards in the GDG DevFest PhilippinesA/B testing with Google Analytics Content Experiments → CollabSpot Twitter loading tweets... Recent Blog Posts CollabSpot Boards Updates (v120830c) Setting up PHP and WordPress on Nginx Making CollabSpot Boards available to Gmail users via Auth CollabSpot Boards Updates Products CollabSpot Boards A Google Apps project management tool based on collaborative boards. CollabSpot Insights A time-saving tool for Highrise users in Gmail. Highrise Gadget Highrise is the famous application from 37signals to track your leads, contacts, and deals. With this gadget, you can do this directly from your Gmail. Intelligent Docs We take your Google Docs template to generate contracts, certificates, marketing materials, NDAs, and other formal documents. Sign up now to get updated in its early development. Follow Us! Twitter Facebook Google+ YouTube Mobile Analytics For Inquiries +1 (415) 735-5559 +33 6 80 90 28 83 [email protected] 71 rue du Faubourg du Pont Neuf 86000 Poitiers, France Contact Us Name * Email *