}

How to serve Django application using uWSGI with Nginx

Created:

Introduction

In this tutorial we will demonstrate you how to setup a Django application using uWSGI and Nginx. We will create a user for the django application and we will use virtualenvs for each application.

Requirements

A non-root user with sudo privileges configured, we will create a new non-root user without sudo for running the application. This tutorial assumes Nginx correctly installed, please follow the install nginx from source code tutorial in case you don't have Nginx installed. We also require to have virtualenv and virtualenvwrapper installed, you can follow this tutorial to learn what is a virtualenv and to install it on our What is a virtualenv and how to install it. Finally a supervisor it's required to manage the gunicorn process for our apps.

Step 1: Create system user

All applications will be executed with the user django_apps, however you can create a new user for each app. We recomend to do this in cases were each application is for a different client or situations were makes sense to have an user for each one.

sudo groupadd --system webapps
sudo useradd --system --gid webapps django_apps --home /var/www/django_apps django_apps
sudo chown -R django_app:users /var/www/django_apps

sudo adduser django_apps

We are going to use /var/www/django_apps as the home directory for out system user. In that directory we are going to have multipley directories for each application we want to deploy. Optinally we can create an user for each app, in this case change the home directory to /var/www/django_app_1.

Step 2: Create virtual envs

For each application we are going to deploy we need to create a separate virtualenv.

su django_apps
mkvirtualenv django_app_1

Step 3: Install dependencies

Usually Django apps cames with a requirements.txt and sometimes with a setup.py that will install dependencies. We recommend to execute tests after all deps were installed.

workon django_app_1
mkdir django_app_1
cd django_app_1
git clone your repo in django_app_1
pip install gunicorn
python setup.py
pip install -r requirements.txt
python manage test

Step 4: Add supervisor to execute wsgi process

We are going to use supervisor to manage the execution of the wsgi process. For this purpose we need to create a script to launch the gunicorn process. Add the supervisor configuration file for our application on /etc/supervisord.d/django_app_1.ini

[program:django_app_1]
command = /var/www/django_apps/.virtualenvs/django_app_1/bin/gunicorn django_app_1.wsgi:application --name django_app_1 --workers 2 --user=django_apps --group=webapps --bind=localhost:5050  --log-level=debug --log-file=/var/www/django_apps/django_app_1.log
user = hello                                                          ; User to run as
stdout_logfile = /var/www/django_apps/gunicorn_supervisor_django_app_1.log   ; Where to write log messages
redirect_stderr = true                                                ; Save stderr in the same log
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8                       ; Set UTF-8 as default encoding

Now update supervisor and start the new application:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start django_app_1

Step 5: Add Nginx virtualhost

Not it's time to add Nginx virtualhost for our django application.

Add a new file to /etc/nginx/sites-available/django_app_1 with the following content

upstream django_app_1_server {
  server unix:/var/www/django_apps/gunicorn.sock fail_timeout=0;
}

server {
    listen   80;
    server_name www.django_app_1.com;

    client_max_body_size 4G;

    access_log /var/www/django_apps/nginx-django_app_1-access.log;
    error_log /var/www/django_apps/nginx-django_app_1-error.log;

    location /static/ {
        alias   /var/www/django_apps/django_app_1/static/;
    }

    location /media/ {
        alias   /var/www/django_apps/django_app_1/media/;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        if (!-f $request_filename) {
            proxy_pass http://django_app_1_server;
            break;
        }
    }
}

Now we are ready to enable the virtual host and restart Nginx.

sudo ln -s /etc/nginx/sites-available/django_app_1 /etc/nginx/sites-enabled/django_app_1
sudo service nginx restart

Everything should be working now!