How To Deploy Django on Nginx, Gunicorn with Postgres

Django is a free and open source web application framework, written in Python, which follows the model–view–controller architectural pattern. It is maintained by the Django Software Foundation (DSF) and its primary goal is to ease the creation of complex, database-driven websites.

This tutorial applies to Debian 7. (but might work on the similar distributions). Before we start with the installation, we need to make sure that our system and our repositories are up to date and then we need to install and create virtualenv.

# sudo apt-get update
# sudo apt-get upgrade
# sudo apt-get install python-virtualenv
# sudo virtualenv /opt/virtualenv

We have now created the directory which will be the home for virtualenv. Before we proceed with Python packages installation, we need to activate our virtualenv.

# source /opt/virtualenv/bin/activate

We will now notice that see that (virtualenv) has been appended to the beginning of the terminal prompt. This will help us know when our virtualenv is active and which virtualenv is active (in case we have multiple virtualenv’s on the VPS). Now it is time to install Django. To do this, we will use pip, a Python package manager much like easy_install:

# pip install django

We now have Django installed. The next step is the database. Most Django users prefer to use PostgreSQL as their database server. It is much more robust than MySQL and the Django ORM works much better with PostgreSQL than MySQL, MSSQL, or others. We don’t need Virtualenv active for PostgreSQL installation, so we can deactivate it:

# deactivate

Then we need to install dependencies for PostgreSQL to work with Django and install PostgreSQL database service:

# sudo apt-get install libpq-dev python-dev
# sudo apt-get install postgresql postgresql-contrib

PostgreSQL is now installed on our VPS. Next thing to install is nginx. We will use nginx as web server, since it fast, light-weight server and compatible with Python. To install it, we simply execute:

# sudo apt-get install nginx

Gunicorn is a very powerful Python WSGI HTTP Server. It is a Python package we need to first activate our virtualenv to install it. With our virtualenv active, we are going to run this command:

# source /opt/myenv/bin/activate
# pip install gunicorn

Gunicorn is now installed in our virtualenv. At this point we have everything we need installed. Now, we need to proceed with the services configuration process. We will start our configuration with PostgreSQL. With PostgreSQL we need to create a database, create a user, and grant the user we created access to the database we created. Start off by running the following command:

# sudo su – postgres

Then, we run this command to create your database and once we have now a database that is named newdb, we will create database user:

# created newdb
# createuser –P

We will get a series of 6 prompts during the process. The first one will ask you for the name of the new user. The next two prompts are for our password and confirmation of password for the new user. For the last 3 prompts just enter “n” and hit “enter”. This just ensures your new users only has access to what you give it access to and nothing else. Now we can start PostgreSQL console and set access for the new user that we just created:

# psql
# GRANT ALL PRIVILEGES ON DATABASE newdb TO newuser;

Now that we have database with user that is able to access it, we need to set those parameters in our Django project. We are going to create new Django project. In order to do that, we need to change to virtualenv directory, activate it and then create new project:

# cd /opt/myenv
# source /opt/myenv/bin/activate
# django-admin.py startproject newproject

We should be able to see a new directory called “newproject” inside our virtualenv directory. This is where our new Django project files live. In order for our project to be able to talk to our database we need to install a additional packages with using pip (while virtualenv still active).

# pip install psycopg2

Now, we change into our new project’s directory and edit settings.py file using our favorite editor. The database settings in the file should look like:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
            'NAME': 'newdb',                      # Or path to database file if using sqlite3.
            # The following settings are not used with sqlite3:
            'USER': 'newuser',
            'PASSWORD': 'password',
            'HOST': 'localhost',                      # Empty for localhost through domain sockets or           '127.0.0.1' for localhost through TCP.
            'PORT': '',                      # Set to empty string for default.
        }

Now, we should move to our main project directory and make sure virtualenv is activated. Once we make sure that virtualenv is active, we can run the following command so that Django can add its initial configuration and other tables to our database:

# cd /opt/virtualenv/newproject
# source /opt/myenv/bin/activate
# python manage.py syncdb

We should get some output describing what tables were installed, followed by a prompt asking if you want to create a superuser. This is optional and depends on if we want to use Django’s authentication system or the Django admin.

Gunicorn configuration is very specific to our applications needs. First we will go over running Gunicorn with default settings. Here is the command to just run default Gunicorn:

# gunicorn_django --bind your-fully-qualified-domain-name.com:8001

If we now point our browser to our-fully-qualified-domain-name.com:8001, we should get the Django welcome screen. Using the command above, we started one worker process only. In production environment we will need more than one. We can control the number of processes from the command line, so if we want to start 5 worker processes, the command will be:

# gunicorn_django –workers=5 --bind your-fully-qualified-domain-name.com:8001

If we want to rung Gunicorn and user other than root, then we have:

# gunicorn_django --workers=5 --user=nobody --bind your-fully-qualified-domain-name.com:8001

Since we might end up having a lot of different input parameters, it is better if we just create configuration file and use that when starting Gunicorn. We can create our configuration file in virtualenv directory for example (/opt/virtualenv/gunicorn_cfg.py), and put the following configuration for the setting we used before:

command = '/opt/myenv/bin/gunicorn'
pythonpath = '/opt/myenv/myproject'
bind = '127.0.0.1:8001'
workers = 5
user = 'nobody'

Now, if we want to run the server, we should execute the following command:

# /opt/myenv/bin/gunicorn -c /opt/myenv/gunicorn_config.py myproject.wsgi

The “-c” flag, tells gunicorn that we have a config file we want to use, which we pass in just after the “-c” flag. We also pass in a Python dotted notation reference to our WSGI file so that Gunicorn knows where our WSGI file is. For further information about Gunicorn, please read the Gunicorn documentation found at gunicorn.org for more on this topic.

The last thing we need to do is to configure nginx. Since we are only setting NGINX to handle static files we need to first decide where our static files will be stored. We should open our settings.py file for our Django project and edit the STATIC_ROOT line to look like this:

STATIC_ROOT = "/opt/virtualenv/static/"

Now that you’ve set up where your static files will be located, we need to configure NGINX to handle the static files and be able to connect to Gunicorn. We should create a new file named /etc/nginx/sites-enabled/newproject and put the following content inside:

server {
    server_name your-fully-qualified-domain-name.com;

    access_log off;

    location /static/ {
        alias /opt/virtualenv/static/;
    }

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';
    }
}

In order to apply settings, we need to restart Nginx and we are good to go:

# sudo service nginx restart

We are done are ready to go now. We can repeated the procedure for creating new application, have another Gunicorn instance running on another port and have additional nginx configuration file. That way we will be able to have many projects and host many website on our VPS.

Try this tutorial on an SSD cloud server for $5.00/month only!

Built for Developers: 512MB RAM, 20GB SSD Disk and 2TB Transfer. 30 second setup.