Django on production. uWSGI + nginx. Detailed guide
- 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.
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:
We create and activate a virtual environment for the software that we will need (below I will tell you how to install uwsgi globally):
Install Django in our virtual environment:
Create a new project and go to its root folder:
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.
One good way to 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.
Create the test.py file:
Launch uWSGI:
Options:
In the browser, go to the address
We see: “Hello, world”, which means that we did everything correctly and the following components work:
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:
If the project has started, stop the development server and run uWSGI as follows:
In the browser, go to the address
We see the start page of Django, which means that we did everything correctly and the following components work:
It is not good that the user's computer directly accesses uWSGI. There must be a web server between the user and uWSGI.
To verify that nginx is installed and running, go to
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).
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:
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,
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:
And execute the command:
Restart nginx:
We put the file with the name, for example, media.png in the folder
In the browser, go to the address
nginx + uWSGI + test.py
We configure the interaction of nginx and test.py through uSWGI.
Almost the same as we did recently, with the exception of one option:
As you remember, we configured nginx (file
If you go to the address
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
And restart nginx:
Launch uWSGI:
This time, the socket option points to a file.
Open in browser
Check the nginx error log, most likely it is in the file.
If you find there something similar to
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:
Or so:
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.
We launch:
In the browser, go to
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
Launch uWSGI:
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:
Install uwsgi:
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:
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:
Create a link to mysite_uwsgi.ini in it:
Launch uWSGI in Emperor mode:
Options:
We check.
In the file
It is done.
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 8000wsgi-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-enabled
create a link to the file mysite_nginx.conf
so 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.png
and, 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.conf
as 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 browser
yourserver.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 filesuid
: id of the user on behalf of whom the process will be launchedgid
: 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.