📜 ⬆️ ⬇️

Nginx + uWSGI + virtualenv + Django on Debian Squeeze

Some time ago, I was puzzled by the search for a way to deploy Django projects, which had two requirements:
  1. Convenient management of starting / stopping / restarting several projects on a single host
  2. 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 restart

Under 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] # try to autoload appropriate plugin if "unknown" option has been specified autoload = true # enable master process manager master = true # spawn 2 uWSGI worker processes workers = 2 # automatically kill workers on master's death no-orphans = true # write master's pid in file /run/uwsgi/<confnamespace>/<confname>/pid pidfile = /run/uwsgi/%(deb-confnamespace)/%n/pid # bind to UNIX socket at /run/uwsgi/<confnamespace>/<confname>/socket socket = /run/uwsgi/%(deb-confnamespace)/%n/socket # set mode of created UNIX socket chmod-socket = 660 # place timestamps into log log-date = true # user identifier of uWSGI processes uid = www-data # group identifier of uWSGI processes gid = www-data 

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.

Source: https://habr.com/ru/post/136295/


All Articles