⬆️ ⬇️

Django on production. uWSGI + nginx. Detailed guide

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:

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


Run uWSGI:

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


Options:



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 




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:

 # 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 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:



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; #   uwsgi  Unix- # server 127.0.0.1:8001; #   uwsgi  - 


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:

 #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 


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 #    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 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:



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.

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



All Articles