Some time ago, I was puzzled by the search for a way to deploy Django projects, which had two requirements:
- Convenient management of starting / stopping / restarting several projects on a single host
- Support for different virtual environments for different projects
On the second point, my choice leaned in favor of Nginx + uWSGI. For the first of the options I considered, I liked the strapping for uWSGI in Debian the most.
Software installation
UWSGI support appeared in Nginx from version 0.8.40, but neither the first nor the second in the stable Debian branch exists. Therefore, we will take Nginx from backports, and uWSGI from an unstable branch. To do this, add the following lines to /etc/apt/sources.list:
deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free deb http://ftp.ru.debian.org/debian testing main non-free contrib deb http://ftp.ru.debian.org/debian unstable main non-free contrib 
And create something like / etc / apt / preferences:
 Package: * Pin: release a=stable Pin-Priority: 700 Package: * Pin: release a=squeeze-backports Pin-Priority: 675 Package: * Pin: release a=testing Pin-Priority: 650 Package: * Pin: release a=unstable Pin-Priority: 600 
Synchronize using 
aptitude update and install the necessary packages:
 aptitude -t squeeze-backports install nginx aptitude -t unstable install uwsgi aptitude -t unstable install uwsgi-plugin-python aptitude -t unstable install python-virtualenv 
Directory structure for projects
Consider a deployment for an example project. For definiteness, suppose that all projects are located in the 
proj subdirectory of the 
user's home directory 
web . Also in 
proj there is a 
static subdirectory where static files of projects will be placed, for the distribution of which Nginx will be responsible. For the example project, we get the following paths:
 /home/web/proj/example /home/web/proj/static/example 
In the 
settings.py of the example project we have the settings:
 STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '../static/example')) STATIC_URL = '/static/' 
Thus, the 
collectstatic management team will collect all project statics in 
/ home / web / proj / static / example .
The virtual environment for the example project will be in 
/ home / web / envs / example .
Setting uWSGI and Nginx
The configuration file uWSGI for the example project will be called 
/etc/uwsgi/apps-available/example.ini and will look like this:
 [uwsgi] plugins = python27 virtualenv = /home/web/envs/example/ chdir = /home/web/proj/example/ pythonpath = .. env = DJANGO_SETTINGS_MODULE=example.settings module = django.core.handlers.wsgi:WSGIHandler() touch-reload = /home/web/proj/example/touchme 
We also create a symbolic link to it in 
/ etc / uwsgi / apps-enabled :
 cd /etc/uwsgi/apps-enabled ln -s ../apps-available/example.ini . 
Then we start the uWSGI daemon: 
/etc/init.d/uwsgi start example')
The Nginx configuration file is called 
/ etc / nginx / sites-available / example . Its minimum option may be:
 server { listen 80; server_name example; access_log /var/log/nginx/example.access.log; error_log /var/log/nginx/example.error.log; location /static/ { alias /home/web/proj/static/example/; } location / { include uwsgi_params; uwsgi_pass unix:///var/run/uwsgi/app/example/socket; } } 
Similarly, we create a symbolic link in / etc / nginx / sites-enabled:
 cd /etc/nginx/sites-enabled/ ln -s ../sites-available/example . 
And restart Nginx: 
/etc/init.d/nginx restartUnder the hood
First, I will briefly discuss the parameters in the uWSGI configuration file. The 
plugins option explicitly specifies the version of Python. The 
chdir and 
pythonpath parameters add the project directory and its parent directory to the Python search path. The 
env and 
module parameters allow you to do without creating a special script to launch the project with the uWSGI daemon. The 
touch-reload option allows you to reload the project using the 
touch / home / web / proj / example / touchme command .
Such a concise configuration file for uWSGI turned out because the startup script 
/etc/init.d/uwsgi uses another configuration file 
/usr/share/uwsgi/conf/default.ini , which for all other necessary parameters are set reasonable enough values for default If necessary, you can override them in 
/etc/uwsgi/apps-available/example.ini . After removing some of the comments, the contents of 
/usr/share/uwsgi/conf/default.ini will be as follows:
 [uwsgi]  
The concept of a 
configuration namespace was introduced in uWSGI in Debian. In 
default.ini, it is represented using the variable 
% (deb-confnamespace) with the default value of 
app . The name of the configuration namespace is defined as follows: the start script 
/etc/init.d/uwsgi searches in the 
/ etc / uwsgi directory for all subdirectories ending in 
s-enabled , and the part of the subdirectory name that precedes 
s-enabled becomes the name of the configuration space for files in this subdirectory. In our case, it would be possible to create more familiar subdirectories of 
sites-available and 
sites-enabled in 
/ etc / uwsgi , in which you place the configuration file 
example.ini and a symbolic link to it, respectively; pidfile and socket for this configuration would be in 
/ run / uwsgi / site / example / pid and 
/ run / uwsgi / site / example / socket , and the uWSGI daemon for this configuration would be controlled using the 
/etc/init.d/ commands 
uwsgi start | stop | restart site / example . If there is no prefix, the 
app namespace is implied.