Django + NGiNX!

Have I said that Python is a solid programming language yet? As a sequence of our last post, I’m going to show you how python works on the web itself, by deploying one of the most famous web frameworks available today: Django! We’re going to work on a NGiNX web server powered by Debian and MariaDB, aiming to focus on resource usage while our ideas will be guarded by Django’s stability!

Why not use a Development Environment?

Yes, it’ll be better to start creating a development environment building an environment where you can freely Destroy Everything You Touch! Fact is, it’s kinda boring to install the services one by one and, if we want to be able to destroy and recreate the environment easily, without wasting much time, we can use Vagrant!

With Vagrant it’s possible to deploy an environment in a few minutes! We must have a provider (such as VirtualBox) in order to build Vagrant Boxes. Keep in mind that the latest version of virtualbox (5.2) will only work with the latest Vagrant version, which is 2.2.0.

For this tutorial I’ve created a solid Vagrant Box based on bento/debian9.5, installing a few packages for our Django Application. You can find out more information about this box on the link below:

To build this box, you must take the following steps, first we need to add the box on our Vagrant environment:

$ vagrant box add marcelfox/debian9_nginx

Then we must start our box with:

$ vagrant init marcelfox/debian9_nginx

The last command will create the Vagrantfile which controls the basics on our box such as Networking and so forth. Since we’ll be accessing our machine through our browser, we must edit the Vagrantfile, uncommenting the following line: "forwarded_port", guest: 80, host: 8080

This line will inform Vagrant that all HTTP requests made to ‘localhost:8080’ will be forwarded as a normal HTTP to our box, so we’ll be able to access the web server running on the box through 8080. Nice, isn’t? =)

Ok then! Let’s bring our debian9_nginx box online and the access it through SSH:

$ vagrant up
$ vagrant ssh

Creating our first Server Block:

First, let’s start creating the directory which will respond our Document Root. In our example, we’re going to create the following directory:

$ sudo mkdir /var/www/vagrant.dom

Then, let’s give to our vagrant user the ownership over the application’s Document Root:

$ sudo chown -R vagrant: /var/www/vagrant.dom/

Alright! Now, why not give a shout with a big “Hello World!” from an index.html?  It’s simple:

$ echo '<h1>"Hello World!"</h1>' >> /var/www/vagrant.dom/index.html

But, how NGiNX will understand this? It’s time to build a very basic Server Block, just to point the Document Root of our future Django Application. Our Server Block will be served in the following file:

$ sudo nano /etc/nginx/sites-available/vagrant

Now you must add the Server Block content. It’s important to notice that in the server_name section, we’re informing that our application will respond to a fake domain, which will be vagrant.dom:

server {
    listen 80;
    listen [::]:80;

    server_name vagrant.dom www.vagrant.dom;

    root /var/www/vagrant.dom;
    index index.html;

    location / {
    try_files $uri $uri/ =404;

In order for this Server Block being activated onto our web server, we must generate a symbolic link to the nginx sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/vagrant /etc/nginx/sites-enabled

Ok! Now we must restart our nginx server!  Our application will be reachable on our host with vagrant.dom:8080. Our machine needs to understand this fake domain, and we can achieve that by editing out /etc/hosts, adding the following line at the bottom of our file:    vagrant.dom

Now your machine sees the fake domain vagrant.dom. Try to visit the following link in your web browser:


OK! Our server is up, now let’s create our virtualenv to deploy our Django Application!


We’re going to take a step further and we’ll deploy the latest version available of Django. Also, we’re gonna work with Python 3 so our virtualenv must support this version. To build our virtualenv we’ll use virtualenvwrapper which is a fine piece of virtualenv abstraction. To create our virtualenv, we must execute the following command:

$ mkvirtualenv -p /usr/bin/python3.5 virtualenv

You’ll notice that virtualenvwrapper will activate the new virtualenv automatically, so we’ll be able to install our packages right away:

$ pip install django==2.1.2

Ok, after the installation has been completed we’ll create our Django project inside our Document Root. Change directory to our Document Root in order to create e simple project with django-admin:

$ cd /var/www/vagrant.dom/
$ django-admin startproject mysite

We must inform our application that it’ll respond to our fake domain, by informing it on the ‘ALLOWED_HOSTS’ section, in our application setting. So edit the settings file under mysites/mysites/ and adjust the ‘ALLOWED_HOSTS’ section to be exactly like:

ALLOWED_HOSTS = ['vagrant.dom']


The uWSGI is a module that responds to python application and NGiNX will serve our Django application from a uWSGI file. Let’s create our mysite.ini file:

$ nano /etc/uwsgi/apps-available/mysite.ini



plugins = python3
chdir = /var/www/vagrant.dom/mysite
module = mysite.wsgi
home = /home/vagrant/.virtualenvs/virtualenv/

uid = vagrant
gid = vagrant

master = true
processes = 10
socket = /var/www/vagrant.dom/mysite/mysite.sock
chmod-socket = 666
vacuum = true

This file will be executed by our uWSGI service and, as NGiNX service does, we must also create a symbolic link to uwsgi ‘apps-anabled’ for our application to be available on our system:

$ sudo ln -s /etc/uwsgi/apps-available/mysite.ini /etc/uwsgi/apps-enabled

Restart the uWSGI service:

$ sudo systemctl restart uwsgi

So far, so good! But our Server Block does not respond our uwsgi ini application. In order to NGiNX be able to respond our mysite.ini,  we must edit the /etc/nginx/sites-available/vagrant to be exactly like that:

upstream django {
    server unix:///var/www/vagrant.dom/mysite/mysite.sock;

server {
    listen 80;
    server_name vagrant.dom;
    charset utf-8;

    location /media {
        alias /var/www/vagrant.dom/mysite/media;

    location /static {
        alias /var/www/vagrant.dom/mysite/static;

    location / {
        uwsgi_pass django;
        include /etc/nginx/uwsgi_params;

Now you only have to restart both uWSGI and NGiNX services and access the fake domain link:


I think that it was a good starting point and again, is just the surface! Why not continue our Django aplication in our development environment powered by Vagrant? Maybe another time!

Related Links:

Leave a Reply

Your email address will not be published. Required fields are marked *