Deploy Django app with Nginx, Gunicorn, PostgreSQL & Supervisor in Linux— 2021

Mandanka Rajan
4 min readJul 16, 2021

Currently we have latest deployment steps using docker or CI or CD tools. Even though I am writing this blogs for those who are beginner and want to deploy manually.

Installation based on :

Python3 , Django, Supervisor, Gunicorn, Postgres , Nginx

  1. First start with the updating packages that are already available on server.
$ sudo apt-get update
$ sudo apt-get upgrade

2. Install python3 and basic system dependencies

$ sudo apt install python-is-python3$ sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx python3.8-venv supervisor

3. PostgreSQL setup ( Optional )

$ sudo -u postgres psqlCREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';
ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myprojectuser SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;\q-------If you want to Change postgres user password:ALTER USER postgres PASSWORD 'myPassword';

4. Create environment and and install the requirements using requirements.txt

python -m venv envsource env/bin/activatepip install -r requirements.txt install below libs if not add in requirements.txt 
- pip install psycopg2
- pip install gunicorn

5. Changes in the settings.py

ALLOWED_HOSTS = ['<your server's IP or domain name>']...
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'django_db',
'USER': 'db_user',
'PASSWORD': '<password you entered when creating db_user>',
'HOST': 'localhost',
'PORT': '5432', # Set to empty string for default.
}
}

6. Now you have gunicorn working, test it by running

gunicorn myproject.wsgi:application --bind 0.0.0.0:8001

7. If it works,

Let make it more configure. Create bash file and paste below code.

#!/bin/bash

NAME="myproject" # Name of the application
DJANGODIR=/home/ubuntu/myproject # Django project directory
SOCKFILE=/home/ubuntu/run/gunicorn.sock # communicate through unix socket
USER=ubuntu # the user to run as
GROUP=ubuntu # the group to run as
NUM_WORKERS=3 # processes Gunicorn spawn
DJANGO_SETTINGS_MODULE=myproject.settings # which settings file should Django use
DJANGO_WSGI_MODULE=myproject.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"

# Activate the virtual environment

cd $DJANGODIR
source /home/ubuntu/env/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

# Create the run directory if it doesn't exist

RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

# Start your Django Unicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)

exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=-

Now make this script executable.

$ sudo chmod u+x gunicorn_start.bash

8. To supervise any program through supervisor, you need to create configuration file. Create file — /etc/supervisor/conf.d/myproject.conf

Copy below content and paste it on above created file ( myproject.conf )

[program: myproject]
command = /home/ubuntu/gunicorn_start.bash
user = ubuntu
stdout_logfile = /home/ubuntu/logs/gunicorn_supervisor.log
redirect_stderr = true
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8

9. Create log file

mkdir -p /home/ubuntu/logs/
touch /home/ubuntu/logs/gunicorn_supervisor.log

10. Now for supervisor we should reread configuration files and update it so the our newly configuration file get add.

$ sudo supervisorctl reread$ sudo supervisorctl update# For Ubuntu 16.04 + :$ sudo systemctl restart supervisor$ sudo systemctl enable supervisor# For all services$ sudo supervisorctl status all$ sudo supervisorctl start all $ sudo supervisorctl stop all$ sudo supervisorctl restart all

11. For Nginx configuration:

create nginx configuration file for our application inside /etc/nginx/sites-available/ directory. create file with .conf extension.

upstream my_project_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server unix:/home/ubuntu/run/gunicorn.sock fail_timeout=0;
}

server {

listen 80;
server_name <your domain name>;

client_max_body_size 4G;
access_log /home/ubuntu/logs/nginx-access.log;
error_log /home/ubuntu/logs/nginx-error.log;

location /static/ {
alias /home/ubuntu/myproject/static/;
}

location /media/ {
alias /home/ubuntu/myproject/media/;
}

location / {

# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;

# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;

# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;

# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;

# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://sample_project_server;
break;
}
}

# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/ubuntu/myproject/static/;
}
}

12. After this we will need to create symbolic link for it, in the /etc/nginx/sites-enabled directory.

sudo ln -s /etc/nginx/sites-available/myproject.conf /etc/nginx/sites-enabled/myproject.conf

13. Now, start the Nginx.

$ sudo service nginx startor$ sudo /etc/init.d/nginx restart

--

--

Mandanka Rajan

Feats to Explore, learn, adapt and share the best ways to become more successful than what I am today