Step 0 – Update and upgrade
We are using Ubuntu 16.04 LTS for this tutorial

apt-get update update the list of available packages and their versions, but it does not install or upgrade any packages. apt-get upgrade actually installs newer versions of the packages you have. After updating the lists, the package manager knows about available updates for the software you have installed.
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get upgrade
Enable SSH (optional)
In case of Ubuntu 16.04 server, ssh isn’t enabled.
$ sudo apt-get purge openssh-server
$ sudo apt-get install openssh-server
$ sudo apt-get install openssh-server
Step 1 – Install the dev packages
The *-dev packages contain the C header files (statically compiled versions i.e. *.so files).
$ sudo apt-get install build-essential libpq-dev libssl-dev openssl libffi-dev zlib1g-dev
Step 2 – Install Python 3.6 (optional)
By default Ubuntu 16.04 LTS has Python 3.5.2 installed. It’s a good practice to start with the latest stable version – Python 3.6.x. Problem is Python 3.6 is not available for direct install, via the default repositories, but as third party PPA. Here’s a step-by-step guide for installing Python 3.6 on Ubuntu.
Install Python dev and pip
$ sudo apt-get install vim python3-pip python3-dev software-properties-common python-software-properties
Add Python 3.6 repository
$ sudo add-apt-repository ppa:jonathonf/python-3.6
Update and install
$ sudo apt-get update
$ sudo apt-get install python3.6
$ sudo apt-get install python3.6

Create virtual environment
$ sudo pip3 install virtualenv
$ virtualenv -p /usr/bin/python3.6 ~/virtualenvs/venv_devopspy
$ source virtualenvs/venv_devopspy/bin/activate
(venv_devopspy) nahmed@ubuntu:~$
$ virtualenv -p /usr/bin/python3.6 ~/virtualenvs/venv_devopspy
$ source virtualenvs/venv_devopspy/bin/activate
(venv_devopspy) nahmed@ubuntu:~$

Step 3 – Install and configure Postgresql
Here’s a step-by-step guide for installing PostgreSQL on Ubuntu.
Add Postgresql repository
$ sudo add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -sc)-pgdg main"
$ wget -q -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$ wget -q -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
Install Postgresql 9.6
$ sudo apt-get update
$ sudo apt-get install postgresql-9.6 postgresql-contrib
$ sudo apt-get install postgresql-9.6 postgresql-contrib

Create user and database
The Posgresql installation itself creates the postgres user, and psql is the command-line utility for PostgreSQL.
$ sudo -u postgres psql postgres
postgres=# create user devopspy_user with password 'devopspy!';
postgres=# create database devopspy_db;
postgres=# grant all privileges on database devopspy_db to devopspy_user;
postgres=# \q
postgres=# create user devopspy_user with password 'devopspy!';
postgres=# create database devopspy_db;
postgres=# grant all privileges on database devopspy_db to devopspy_user;
postgres=# \q
Verify
$ psql -h localhost devopspy_db -U devopspy_user -W

Step 4 – Clone or create Django project
If you already have your Django project ready, or have it as a Git repository, the following steps are not for for you.
Make sure you have the virtual environment activated (created above).
Install Django
$ pip install django==1.11
Start project
$ mkdir /var/www/
$ sudo chown -R nahmed:nahmed /var/www/
$ cd /var/www/
$ django-admin startproject devops_project
$ sudo chown -R nahmed:nahmed /var/www/
$ cd /var/www/
$ django-admin startproject devops_project
Install requirements
$ cd devops_project
$ pip install psycopg2
$ pip install psycopg2
Create requirements.txt (optional)
$ pip freeze > requirements.txt
Add DB settings
You can find the settings.py in the project folder i.e. inside /var/www/devops_project/devops_project. Open settings.py using editor of your choice
vim settings.py
Update the DATABASES dictionary as follows:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'devopspy_db',
'USER': 'devopspy_user',
'PASSWORD': 'devopspy!',
'HOST': 'localhost',
'PORT': 5432,
}
}
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'devopspy_db',
'USER': 'devopspy_user',
'PASSWORD': 'devopspy!',
'HOST': 'localhost',
'PORT': 5432,
}
}
update ALLOWED_HOST
ALLOWED_HOSTS = ['*']
Make migrations
You can find the manage.py at project root
$ python3.6 manage.py migrate

Verify (optional)
This step is to verify if our Django project is Ok. You must shutdown the server using ctrl+c. As gunicorn will be using the same port i.e. 8000
python3.6 manage.py runserver

Step 5 – Install and configure Gunicorn
$ pip install gunicorn
To start gunicorn, it’ll be the Django app server, for which NginX will be acting as a reverse proxy.
Option 1 – Start the app server
Execute the following at project root – it is not recommend for production setups, you must register gunicorn as systemd service (option 2, below)
$ gunicorn -b 0.0.0.0:8000 devops_project.wsgi
Option 2 – Register Gunicorn systemd service
Create a service file
$ sudo vim /etc/systemd/system/gunicorn.service
Copy paste the following into the gunicorn.service file
[Unit]
Description=gunicorn daemon
After=network.target[Service]
User=nahmed
Group=www-data
WorkingDirectory=/var/www/devops_project
ExecStart=/home/nahmed/virtualenvs/venv_devopspy/bin/gunicorn --access-logfile - --workers 3 --bind unix:/var/www/devops_project.sock devops_project.wsgi
[Install]
WantedBy=multi-user.target
Description=gunicorn daemon
After=network.target[Service]
User=nahmed
Group=www-data
WorkingDirectory=/var/www/devops_project
ExecStart=/home/nahmed/virtualenvs/venv_devopspy/bin/gunicorn --access-logfile - --workers 3 --bind unix:/var/www/devops_project.sock devops_project.wsgi
[Install]
WantedBy=multi-user.target

Start the gunicorn service
$ sudo systemctl status gunicorn
$ sudo systemctl daemon-reload
$ sudo systemctl restart gunicorn
$ sudo systemctl enable gunicorn.service
$ sudo systemctl daemon-reload
$ sudo systemctl restart gunicorn
$ sudo systemctl enable gunicorn.service
Step 6 – Install and configure NginX
Install NginX
$ sudo apt-get install nginx
Create project conf
$ sudo vim /etc/nginx/sites-available/devops_project
Add the following to the devops_project conf file
server {
listen 80;
server_name 0.0.0.0;location / {
include proxy_params;
proxy_pass http://unix:/var/www/devops_project.sock;
}
}
listen 80;
server_name 0.0.0.0;location / {
include proxy_params;
proxy_pass http://unix:/var/www/devops_project.sock;
}
}
Delete default conf (optional)
As it has a default content set to be served on port 80. In case you want to listen at some port other than 80, no need to delete the default.
$ sudo rm -rf /etc/nginx/sites-enabled/default
Enable project conf
$ sudo ln -s /etc/nginx/sites-available/devops_project /etc/nginx/sites-enabled
Verify NginX conf
NginX configuration can be validated for any errors before restarting NginX, and putting it in down state.
sudo nginx -t
Output
nahmed@ubuntu:/etc/nginx/sites-available$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Restart and enable NginX
$ sudo systemctl restart nginx
$ sudo systemctl enable nginx
$ sudo systemctl enable nginx
Verification
