Swipe left or right to navigate to next or previous post

Ultimate guide to deploy django in Nginx Server with supervisor and Gunicorn

28 Mar 2022 . category: Server . Comments
#Django #Nginx #Server

Ultimate guide to deploy django in Nginx Server

This blog post is about how to install Django with Nginx as server and Supervisor for process control and Gunicorn as Python WSGI HTTP Server. We will be using the Ubuntu OS. Basic understanding of the python/Django and Linux environment is needed to follow along the tutorial. The steps to setup is similar in all the cloud services. However, following steps are based on AWS ec2

Basic architecture of the setup environment.

Django Nginx Setup Architecture

The software needed are:

  1. Ubuntu Server
  2. Nginx Server
  3. Django App
  4. Gunicorn (WSGI server)
  5. Domain or ip of server

Install packages and their dependencies

    sudo apt update && sudo apt upgrade -y
    sudo apt install python3-dev gcc libssl-dev virtualenv supervisor nginx gunicorn -y

Clone the project

Clone the project git. For the tutorial purpose, we have the project on the /home/ubuntu/api folder.

    git clone github_url

Setup Virtual environment

Create virtual environment

    virtualenv venv -p python3

-p python3 parameter is used to set the python3 interpreter.

Activate Virtual environment

    source venv/bin/activate

Install the project dependencies

    pip3 install -r requirements.txt

Setup the environment file

Copy the environment file

I have the environment file env.example.py inside separate folder in config/settings.

    sudo cp config/settings/env.example.py config/settings/env.py
    sudo nano config/settings/env.py

Most of the project have .env.example file in the root folder of the project. Copy and update the file

    sudo cp .env.example .env
    sudo nano .env

Make folder for logs, media and static files

logs folder is required to store the logs files. media files is used to store the uploaded files and static folder is used to store the static files of the project. The folder for logs, static files and media and folder can be configured in env file.

Following configuration can be added for static and media files

    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR,'static')
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

To create the blank logs, static and media folder. Run following command

    mkdir logs static media

Update the static files

    python manage.py collectstatic

Setup Gunicorn, Supervisor

We need to create the various folder for the gunicorn and supervisor. For this tutorial purpose, we create these folders along side the project folder inside /home/ubuntu/

    mkdir bin logs run
Create a log file for gunicorn inside the logs folder
    touch /home/ubuntu/logs/gunicorn-error.log

Configure the database

You can choose the mysql or the postgres database based on your choice

For Mysql Setup

Mysql Installation and its dependencies

    sudo apt install mysql-server libmysqlclient-dev default-libmysqlclient-dev -y
    sudo systemctl start mysql && sudo systemctl enable mysql
    sudo mysql_secure_installation utility

Create user, database and grant permissions

    sudo mysql
    CREATE USER 'project_user'@'localhost' IDENTIFIED BY 'password';
    create database myproject_db character set utf8mb4; 
    grant all privileges on project_user.* to 'myproject_db'@'localhost' identified by 'password';

For Postgres

Postgres Installation and its dependencies

    sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib -y
    sudo systemctl enable supervisor  && sudo systemctl start supervisor

Create user, database and grant permissions

    sudo -u postgres createuser project_user;
    sudo -u postgres createdb myproject_db;

Update user password and grant permissions to user

    sudo -u postgres psql;
    alter user 'project_user' with encrypted password 'password';
    grant all privileges on database 'myproject_db' to 'project_user';

Basic Postgres commands

    sudo service postgresql stop
    sudo service postgresql start
    sudo service postgresql restart

Create the migration files and install the migrations

    source venv/bin/activate
    python manage.py makemigrations
    python manage.py migrate

Gunicorn setup

Create a gunicorn_start file inside the /home/ubuntu/bin

Create a gunicorn_start file

    sudo nano bin/gunicorn_start

Update the file content with following content

Update the NAME, DIR, USER, GROUP and workers values based on the project setting

    #!/bin/bash
    NAME="project_name"
    DIR=/home/ubuntu/api
    USER=ubuntu
    GROUP=ubuntu
    WORKERS=3
    BIND=unix:/home/ubuntu/run/gunicorn.sock
    DJANGO_SETTINGS_MODULE=config.settings
    DJANGO_WSGI_MODULE=config.wsgi
    LOG_LEVEL=error
    
    cd $DIR
    source venv/bin/activate
    
    export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
    export PYTHONPATH=$DIR:$PYTHONPATH
    
    exec venv/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
      --name $NAME \
      --workers $WORKERS \
      --user=$USER \
      --group=$GROUP \
      --bind=$BIND \
      --log-level=$LOG_LEVEL \
      --log-file=-

DJANGO_SETTINGS_MODULE and DJANGO_WSGI_MODULE path must be with respect to project. Since my all the settings are inside config folder, so all its value start from config.

Later on, while running the gunicorn, if you see the path error. Please use the absolute folder from the root. like \home\USER_NAME\YOUR_PROJECT_NAME

Add the executable permission to the gunicorn_start file

    sudo chmod u+x bin/gunicorn_start

Supervisor Configuration

Supervisor is used to monitor and control a number of process running in unix based operating system.

Create a supervisor file

Create new file inside /etc/supervisor/conf.d . For the sake of tutorials purpose, we are using the myproject.conf

    sudo nano /etc/supervisor/conf.d/myproject.conf

Open the configuration file using following command

    sudo nano /etc/supervisor/conf.d/myproject.conf

Update the basic supervisor configuration in myproject.conf file

    [program:myproject]
    command=sh /home/ubuntu/bin/gunicorn_start
    user=ubuntu
    autostart=true
    autorestart=true
    redirect_stderr=true
    stdout_logfile=/home/ubuntu/logs/gunicorn-error.log

You can change the path to gunicorn_start if you store the file in different location. Update the username according to the user

Check the gunicorn and supervisor configuration

Following command helps to reread and update the currently updated supervisor commands

    sudo supervisorctl reread
    sudo supervisorctl update

Check the status of the configuration

    sudo supervisorctl status myproject

If we can see the myproject running and uptime, then everything is

Create a nginx configuration

Create a configuration file and update the following configuration

    sudo nano /etc/nginx/sites-available/myproject.conf
    upstream app_server {
        server unix:/home/ubuntu/run/gunicorn.sock fail_timeout=0;
    }
    
    server {
        listen 80;
    
        # add here the ip address of your server
        # or a domain pointing to that ip (like example.com or www.example.com)
        # You can add the multiple server_name with http, https and www
        server_name test.com;
        # server_name test.com http.test.com https.test.com www.test.com;
    
        keepalive_timeout 5;
        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/api/static/;
        }
    
        location /media/ {
            alias /home/ubuntu/api/media/; 
        }
      

        # checks for static file, if not found proxy to app
        location / {
            try_files $uri @proxy_to_app;
        }
    
        location @proxy_to_app {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_pass http://app_server;
        }
    }

Check the validity of nginx configuration

    sudo nginx -t

Create symbolic link to /etc/nginx/sites-enabled

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

Remove the default configuration file

    sudo rm /etc/nginx/sites-enabled/default

Restart the nginx server and supervisor

    sudo systemctl restart nginx
    sudo systemctl restart supervisor

Some useful commands

Check the nginx error

    sudo nginx -c /etc/nginx/nginx.conf -t
    sudo nginx -t

Reload and Restart supervision

    sudo supervisorctl reload
    sudo supervisorctl restart myproject

Some useful Supervisor commands

    sudo nano gunicorn_start 
    sudo supervisorctl reread
    sudo supervisorctl update
    sudo supervisorctl status myproject

Tapan B.K. | Full Stack Software Engineer

Tapan B.K. is Full Stack Software Engineer. In his spare time, Tapan likes to watch movies, visit new places.