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.