Django on production. uWSGI + nginx. Detailed guide

Original author: wiki
  • Transfer
  • Tutorial
Here is a guide to setting up a production environment for Django. The necessary steps to configure Django, uWSGI and nginx will be described here. The guide covers all three components — the full stack of server software for web applications.

It assumes that you are using a Unix-like operating system and aptitude-equivalent package manager. Finding the equivalent of aptitude for almost any operating system, including Mac OS X, is easy for you.

The manual is written for versions of Django 1.4 or higher. If you are using an earlier version, you will have to find the wsgi module for it yourself. You will also notice that the file structure of the project will be slightly different from the one presented here.

General idea


The web server can, upon request, give files to users from its file system, however, it cannot directly work with Django applications. The web server needs an interface that will launch the Django application, send it a request from the user and return a response.

To accomplish these tasks, the Web Server Gateway Interface - WSGI - a standard for the interaction of Python programs and a web server, was developed.

uWSGI is one of the WSGI implementations. In this guide, we will install and configure uWSGI to create a Unix socket and interact with the web server using the WSGI protocol.

The full stack of components will look like this:
Пользователь <-> Веб-сервер <-> Сокет <-> uwsgi <-> Django

Before installing uWSGI


virtualenv


We create and activate a virtual environment for the software that we will need (below I will tell you how to install uwsgi globally):
virtualenv uwsgi-tutorial
cd uwsgi-tutorial
source bin/activate

Django


Install Django in our virtual environment:
pip install Django

Create a new project and go to its root folder:
django-admin.py startproject mysite
cd mysite

Domain and Port


In this tutorial, we will use the domain yourserver.com for our training project. You will need to replace it with your own domain name or IP address of your server.

To receive requests from users, we will use port 8000. You can use any other port. I chose exactly 8000, because its use will not lead to conflicts with other tasks performed by the server.

Installation and basic configuration of uWSGI


Install uWSGI in a virtual environment


One good way to install uWSGI:
pip install uwsgi

We will need Python development packages. If you are using Debian or a Debian-based operating system (such as Ubuntu or Mint), you need to install the pythonX.Y-dev package, where XY is the version of Python you need.

Check


Create the test.py file:
# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3
    #return ["Hello World"] # python2

Launch uWSGI:
uwsgi --http :8000 --wsgi-file test.py

Options:
  • http: 8000: uses http protocol and port 8000
  • wsgi-file test.py: uwsgi will load a specific file (in our case test.py)

In the browser, go to the address yourserver.com:8000.
We see: “Hello, world”, which means that we did everything correctly and the following components work:
Пользователь <-> uWSGI <-> test.py

Testing Django Application Performance


Now let's make uWSGI work with the Django application, and not with the test.py file.

Check that the newly created mysite project runs on the server for development:
python manage.py runserver 0.0.0.0:8000

If the project has started, stop the development server and run uWSGI as follows:
uwsgi --http :8000 --module mysite.wsgi

  • module mysite.wsgi: uwsgi will load the mysite.wsgi module

In the browser, go to the address yourserver.com:8000.
We see the start page of Django, which means that we did everything correctly and the following components work:
Пользователь <-> uWSGI <-> Django


It is not good that the user's computer directly accesses uWSGI. There must be a web server between the user and uWSGI.

Installation and basic setup of nginx


Installing and starting nginx


sudo apt-get install nginx
sudo /etc/init.d/nginx start 

To verify that nginx is installed and running, go to yourserver.com:80. If you see the message “Welcome to nginx!”, Then all ok and the following components work:
Пользователь <-> Веб-сервер

If you have an eightieth port, change the configuration of nginx so that it uses some other one (in this manual nginx will use port 8000).

Nginx configuration for working with Django


We will need the uwsgi_params file, which can be taken here: github.com/nginx/nginx/blob/master/conf/uwsgi_params .
Download it to the root folder of our project.

Create the mysite_nginx.conf file:
# mysite_nginx.conf
upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # взаимодействие с uwsgi через Unix-сокет (мы воспользуемся этим вариантом позже) 
    server 127.0.0.1:8001; # взаимодействие с uwsgi через веб-порт 
}
# конфигурация веб-сервера
server {
    # порт, который будет слушать веб-сервер в ожидании запросов от пользователй
    listen      8000;
    # доменное имя
    server_name     yourserver.com; # замените на собственный домен или IP адрес
    charset     utf-8;
    # максимальный размер загружаемых на сервер данных
    client_max_body_size 75M;  
    # обслуживание медиа файлов и статики
    location /media  {
        alias /path/to/your/mysite/media;  # расположение медиафайлов (при необходимости измените)
    }
    location /static {
        alias /path/to/your/mysite/static;  # расположение статики (при необходимости измените)
    }
    # Остальные запросы перенаправляются в Django приложение
    location / {
        uwsgi_pass  django;
        include     /path/to/your/mysite/uwsgi_params; # файл uwsgi_params, который мы только что взяли с github
    }
}

This configuration file tells nginx that it should send media and static files to the users from the file system, and redirect all other requests to the Django application. In large projects, it is better to use two servers: one for serving static and media files, and the other for Django applications. With small, and even more so with educational projects, one server will cope.

In the folder, /etc/nginx/sites-enabledcreate a link to the file mysite_nginx.confso nginx sees it:
sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/

Statics in one place


Before starting nginx, put all the statics in the static folder. To do this, add the following line to the mysite / settings.py file:
STATIC_ROOT = os.path.join(BASE_DIR, "static/")

And execute the command:
python manage.py collectstatic

Validation of statics and media


Restart nginx:
sudo /etc/init.d/nginx restart

We put the file with the name, for example, media.png in the folder /path/to/your/project/project/media.

In the browser, go to the address yourserver.com:8000/media/media.pngand, if we see our file, then we did everything right.

nginx + uWSGI + test.py


We configure the interaction of nginx and test.py through uSWGI.
uwsgi --socket :8001 --wsgi-file test.py

Almost the same as we did recently, with the exception of one option:
  • socket :8001: use uWSGI protocol, port 8001

As you remember, we configured nginx (file mysite_nginx.conf) to work with uWSGI through port 8001.

If you go to the address yourserver.com:8001, we won’t see anything, because the browser uses the http protocol, not uWSGI, however, uWSGI will display a message about an attempt to connect to the terminal.

Unix sockets instead of web ports


Until that moment, we used a socket attached to a TCP port (I called it a web port), because it was easier, but in fact it is recommended to use a Unix socket because of the performance advantage.

We edit mysite_nginx.confas follows:
server unix:///path/to/your/mysite/mysite.sock; # взаимодействие с uwsgi через Unix-сокет
# server 127.0.0.1:8001; # взаимодействие с uwsgi через веб-порт 

And restart nginx:
sudo /etc/init.d/nginx restart

Launch uWSGI:
uwsgi --socket mysite.sock --wsgi-file test.py

This time, the socket option points to a file.
Open in browseryourserver.com:8000/

If it didn’t work


Check the nginx error log, most likely it is in the file. var/log/nginx/error.log

If you find there something similar to
connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission denied)

then there is a problem with the permissions of the mysite.sock file. You must make nginx have permission to use this file.

Try running uWSGI like this:
uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666 #много полномочий

Or so:
uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 #более разумно


To avoid access problems in the future, add your user to the www-data group.

The information that uWSGI outputs to the terminal is useful in finding and correcting possible errors or malfunctions.

nginx + uWSGI + Django


We launch:
uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=664

In the browser, go to yourserver.com:8000/and see the Django start page.
Пользователь <-> Веб-сервер <-> Сокет <-> uwsgi <-> Django

We've put together the whole chain, but the setup is not finished yet, move on.

UWSGI configuration via ini file


It is very convenient to specify all the options with which we run uWSGI in the ini file, and when starting, transfer only the path to this file.

Create a file mysite_uwsgi.ini:
#mysite_uwsgi.ini 
[uwsgi]
# Настройки, связанные с Django
# Корневая папка проекта (полный путь)
chdir           = /path/to/your/project
# Django wsgi файл
module          = project.wsgi
# полный путь к виртуальному окружению
home            = /path/to/virtualenv
# общие настройки
# master
master          = true
# максимальное количество процессов
processes       = 10
# полный путь к файлу сокета
socket          = /path/to/your/project/mysite.sock
# права доступа к файлу сокета
# chmod-socket    = 664
# очищать окружение от служебных файлов uwsgi по завершению
vacuum          = true

Launch uWSGI:
uwsgi --ini mysite_uwsgi.ini

We check. Everything works? Further.

Install uWSGI globally


So far, uWSGI has been installed in a virtual environment. In order to be able to automatically launch uWSGI when the operating system starts, we will install it globally.

Deactivate the virtual environment:
deactivate

Install uwsgi:
sudo pip install uwsgi
# Или можно установить LTS (с долговременной поддержкой) версию
pip install http://projects.unbit.it/downloads/uwsgi-lts.tar.gz

The uWSGI wiki page describes several installation options . Before you install uWSGI globally, it will not hurt you to decide on the version choice and installation method.

You can run uWSGI with the same command as before:
uwsgi --ini mysite_uwsgi.ini

Emperor Mode


If the server serves several projects, each of which uses uWSGI, then you need to use Emperor mode. In this mode, uWSGI scans the folder with configuration files and for each file starts a separate process (vassal).

If one of the configuration files is changed, uWSGI will restart the corresponding vassal.

Create a folder for configuration files:
sudo mkdir /etc/uwsgi
sudo mkdir /etc/uwsgi/vassals

Create a link to mysite_uwsgi.ini in it:
sudo ln -s /path/to/your/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/

Launch uWSGI in Emperor mode:
sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

Options:
  • emperor: folder with configuration files
  • uid: id of the user on behalf of whom the process will be launched
  • gid: id of the group on behalf of which the process will be launched

We check. yourserver.com:8000/

Automatically launch uWSGI after loading the operating system


In the file /etc/rc.local, before the line “ exit 0” add:
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

It is done.

Also popular now: