Here is a guide to setting up a production environment for Django. It will describe the necessary steps to configure Django, uWSGI and nginx. The manual covers all three components — a complete web application server stack.
The implication is that you are using a Unix-like operating system and a package manager equivalent to aptitude. Finding the equivalent of aptitude for almost any operating system, including Mac OS X, is easy for you.
The guide is written for Django versions 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 project's file structure will be slightly different from the one presented here.
')
General idea
A web server can send files from its file system to users upon request, but 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 was developed - WSGI - the standard of interaction between Python programs and a web server.
uWSGI is one of the implementations of WSGI. In this guide, we will install and configure uWSGI to create a Unix socket and interact with a web server using the WSGI protocol.
The full stack of components will look like this:
<-> - <-> <-> uwsgi <-> Django
Before installing uWSGI
virtualenv
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
Set Django to 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 guide, we will use the domain of 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 using it will not lead to conflicts with other tasks performed by the server.
Installation and basic uWSGI setup
Installing uWSGI in a virtual environment
One of the good ways to install uWSGI:
pip install uwsgi
We need Python development packages. If you are using Debian or a Debian-based operating system (for example, Ubuntu or Mint), you need to install the pythonX.Y-dev package, where XY is the version of Python you need.
Check
Create a test.py file:
Run uWSGI:
uwsgi --http :8000 --wsgi-file test.py
Options:
http: 8000
: uses the http protocol and port 8000
wsgi-file test.py
: uwsgi will download a specific file (in our case test.py)
In the browser go to
yourserver.com:8000
yourserver.com:8000
.
We see: “Hello, world”, it means that we did everything correctly and the following components work:
<-> uWSGI <-> test.py
Test Django application
Now we’ll make uWSGI work with the Django application, not with the test.py file.
Verify that the newly created mysite project runs on the development server:
python manage.py runserver 0.0.0.0:8000
If the project has started, stop the development server and start uWSGI as follows:
uwsgi --http :8000 --module mysite.wsgi
module mysite.wsgi
: uwsgi will load the module mysite.wsgi
In the browser go to
yourserver.com:8000
yourserver.com:8000
.
We see the Django start page, which means we did everything correctly and the following components work:
<-> uWSGI <-> Django
It is not good that the user's computer directly refers to uWSGI. There must be a web server between the user and uWSGI.
Installation and basic nginx configuration
Install and run 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
yourserver.com:80
. If you see the message “Welcome to nginx!”, It means that all OK and the following components work:
<-> -
If you are busy port 80, change the nginx configuration so that it uses some other one (in this guide nginx will use port 8000).
Nginx configuration for working with Django
We will need the uwsgi_params file, which can be found here:
github.com/nginx/nginx/blob/master/conf/uwsgi_params .
Download it to the root folder of our project.
Create the file mysite_nginx.conf:
This configuration file tells nginx that it should give media and static users files 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 especially with educational projects, one server can handle it.
In the
/etc/nginx/sites-enabled
folder we create a link to the
mysite_nginx.conf
file
mysite_nginx.conf
that nginx can see it:
sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/
Static in one place
Before running nginx, put all the static 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 we execute the command:
python manage.py collectstatic
Static and Media Maintenance Check
Restart nginx:
sudo /etc/init.d/nginx restart
Place the file with the name, for example, media.png in the folder
/path/to/your/project/project/media
.
In the browser go to
yourserver.com:8000/media/media.png
yourserver.com:8000/media/media.png
and if you see our file, it means we did everything right.
nginx + uWSGI + test.py
We configure interaction of nginx and test.py through uSWGI.
uwsgi --socket :8001 --wsgi-file test.py
Almost the same thing we did recently, except for one option:
socket :8001
: we use the 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
yourserver.com:8001
yourserver.com:8001
, we will not see anything, because the browser uses the http protocol, not uWSGI, however uWSGI will display a message about the attempt to connect to the terminal.
Unix sockets instead of web ports
Before that, we used a socket tied 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.
Edit
mysite_nginx.conf
as follows:
server unix:///path/to/your/mysite/mysite.sock;
And restart nginx:
sudo /etc/init.d/nginx restart
Run 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 not earned
Check the nginx error log, most likely it is in the
var/log/nginx/error.log
file
If you find there is something like
connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission denied)
it means there is a problem with the permissions of the mysite.sock file. You must make sure that nginx has 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 prevent future access problems, 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
Run:
uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=664
In the browser, go to
yourserver.com:8000/
yourserver.com:8000/
and see the Django start page.
<-> - <-> <-> uwsgi <-> Django
We have collected the whole chain, but the configuration is not yet complete, go ahead.
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, pass only the path to this file.
Create a
mysite_uwsgi.ini
file:
Run uWSGI:
uwsgi --ini mysite_uwsgi.ini
We are checking. Everything is working? Farther.
Install uWSGI globally
Until now, uWSGI has been installed in a virtual environment. To be able to automatically run uWSGI when the operating system starts, we will install it globally.
Deactivating the virtual environment:
deactivate
Install uwsgi:
sudo pip install uwsgi
The uWSGI wiki page describes several
installation options . Before you install uWSGI globally, it will not hurt you to decide on the choice of version 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 starts a separate process (vassal) for each file.
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/
Run uWSGI in Emperor mode:
sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
Options:
emperor
: configuration file folderuid
: the id of the user on whose behalf the process will be started
gid
: id of the group on behalf of which the process will run
We are checking.
yourserver.com:8000/
Automatic start of uWSGI after loading the operating system
In the
/etc/rc.local
file, before the line “
exit 0
” add:
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
It is done.