Setup Django With Python 3 and Nginx in Vagrant

If you want to setup Django project with Python 3 and Nginx in Vagrant, follow me. At first I used Django one click install image in Digital Ocean, but I got Python 2. I was disappointed. So I plan to use Django with Python 3 in Digital Ocean but first I have to setup it in vagrant for my development purpose. So here are the steps:

Install Vagrant

Go to Vagrant Homepage. Choose your installer file based on your OS. Once it is done:

mkdir project_dir

cd project_dir

vagrant init

Then change the Vagrantfile. Make it like this:

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"

  config.vm.network "private_network", ip: "192.168.33.10"

  config.vm.host_name = "project.dev"
end

Then do this to initiate the vagrant machine. I give project.dev as this vagrant machine’s hostname.

vagrant up

Then go inside vagrant machine, do this:

vagrant ssh

Install Python

I decided not to use Python 3 that comes with Ubuntu because the pip support is broken. There is a way to overcome that problem. But I prefer to use Python from source. My friend does not recommend this solution. But I contribute to Python core regularly (https://hg.python.org/cpython/search/?rev=vajrasky&revcount=160) so I am comfortable with Python from source. I even debated once with Python core developer about Python technical decision. Of course, you are welcome to use Python 3 from Ubuntu.

First, we install the dependencies of building Python from source.

sudo apt-get install build-essential libbz2-dev libncurses5-dev libreadline6-dev libsqlite3-dev libgdbm-dev liblzma-dev tk8.6-dev libssl-dev python3-setuptools

mkdir ~/download

cd ~/download

wget https://www.python.org/ftp/python/3.4.2/Python-3.4.2.tgz

tar -xvf Python-3.4.2.tgz

sudo mkdir /opt/python

sudo chown -R vagrant:vagrant /opt/python

cd Python-3.4.2

./configure --prefix=/opt/python

make

make install

As you can see I installed a bunch of things just to make sure the compiling process of Python runs 100% smooth. All modules will be built.

Setup Nginx

Install Nginx server. It will be the gateway to the outside world. Outsider will be greeted by Nginx before they can be served by Django application.

sudo apt-get install nginx

Then change Nginx config file.

sudo vim /etc/nginx/sites-available/default

Make it like this:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;

    index index.html index.htm;
    server_name project.dev;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://127.0.0.1:8000;
    }

    location /media  {
        alias /vagrant/project_project/project_project/media;
    }

    location /static {
        alias /vagrant/project_project/project_project/static;
    }

    keepalive_timeout 5;

    client_max_body_size 4G;
}

Then restart Nginx.

sudo service nginx restart

Setup Python Virtual Environment

I don’t want to populate system wide directory if I want to install third-party Python libraries. Create a directory for our python virtual environment.

sudo mkdir /opt/project_env

sudo chown vagrant:vagrant /opt/project_env

/opt/python/bin/pyvenv /opt/project_env

It is better to give the permission for Python virtual environment to any user beside root so when we create Python virtual environment, we can avoid sudo. Sudo will use Python from system not your custom Python.

Install Gunicorn and Django

Gunicorn will be our Django webserver.

First, activate Python virtual environment.

source /opt/project_env/bin/activate

Then install Gunicorn.

pip install gunicorn

And install Django.

pip install django

Deactivate the Python virtual environment.

deactivate

Setup PostgreSQL

This will be our database of choice.

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

Then create database.

sudo su - postgres

createdb project_db

createuser project_user

Go inside PostgreSQL command prompt.

psql

Do this to set the password and grant permission.

alter user project_user with password 'penguinbercinta';

grant all privileges on database project_db to project_user;

\q

Get back as vagrant user.

exit

Then install psycopg2 library inside Python virtual environment.

source /opt/project_env/bin/activate

pip install psycopg2

Deactivate the Python virtual environment.

deactivate

Setup Django Application

Create Django application.

source /opt/project_env/bin/activate

cd /vagrant

django-admin startproject project_project

Before you go on, you need to change the setting of Django project so it uses PostgreSQL.

vim /vagrant/project_project/project_project/settings.py

Change the ‘DATABASES’ part to it looks like this:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'project_db',
        'USER': 'project_user',
        'PASSWORD': 'penguinbercinta',
        'HOST': 'localhost',
        'PORT': '',
    }
}

Then migrate database.

cd /vagrant/project_project

python manage.py migrate

deactivate

You should see no errors.

Setup Supervisor

We will use Supervisor to run Gunicorn. This is to make sure we can monitor and restart Gunicorn easily. First, install Supervisor.

sudo apt-get install supervisor

Then add Gunicorn config file for Supervisor.

sudo vim /etc/supervisor/conf.d/gunicorn.conf

Make it like this:

[program:gunicorn]
command=/opt/project_env/bin/gunicorn --bind 0.0.0.0 project_project.wsgi
directory=/vagrant/project_project
user=vagrant
autostart=true
autorestart=true
stderr_logfile=/var/log/gunicorn.err.log
stdout_logfile=/var/log/gunicorn.out.log

The –bind 0.0.0.0 phrase is to make sure we can can access Gunicorn directly without Nginx for development from host.

Restart the Supervisor.

sudo service supervisor restart

The End

To be able to use project.dev in your host (not your vagrant), you need to associate the ip address of vagrant, 192.168.33.10 to project.dev. In Mac or Linux (not in your vagrant), do this:

sudo vim /etc/hosts

Add this line:

192.168.33.10 project.dev

From your browser, open http://project.dev to see your Django application served through Nginx and http://project.dev:8000 to see your Django application served directly with Gunicorn.

You should see something like this:

Initial Django First Page
Initial Django First Page

To install Django on IIS, you can take a look at a blog in Toptal.

2 thoughts on “Setup Django With Python 3 and Nginx in Vagrant

  1. Great article!

    Have you considered standardizing on an OS and making a simple bootstrap file? I’ve been meaning to include a CentOS Python 3 / Django 1.7.5 in a blog post, but haven’t gotten around to it. We run a pretty weird set up at work: RHEL 6, Python 3, Django, with (ugh) SQL Server and Apache (we need CoSign auth). While I wouldn’t wish this stack on anyone, there are a lot of neat how-tos we had to figure out along the way.

    Regards,

    -Tim

    1. Hi Tim,

      I used Ansible to automate this stuff. I use Ubuntu LTS. Yeah, I agree. Your stack is definitely weird. 🙂

      Thanks for reading my article.

      Sky

Leave a Reply

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