Django + Gunicorn + Nginx Setup

Prior to gunicorn and nginx, i’ve tried to user apache + mod_wsgi and failed. Still don’t know why it fail. After 3 days trying, I give up. I have to look for another method, I try using gunicorn dan nginx, and It took me only 2 days for gunicord + nginx setup to works. ūüôā

Here is condition on my Django + Gunicorn + Nginx setup:

  • I use CentOS 7 on my server
  • I create new user for running django (in my case /home/myuser)
  • I install python 3.7.3, django, pandas, django_extensions, virtual environment, gunicorn dan nginx
  • My django project folder is /home/myuser/myproject
  • I put all my django app (created using ‘python startapp myapp apps/myapp’) in /home/myuser/myproject/apps

Here is some of reference I use:

Here is my setup:


import os
import sys

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = get_wsgi_application()


user  nginx; 
worker_processes  1; 

error_log  /var/log/nginx/error.log warn; 
pid        /var/run/; 

events { 
   worker_connections  1024; 

http { 
   include       /etc/nginx/mime.types; 
   default_type  application/octet-stream; 

   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ' 
                     '$status $body_bytes_sent "$http_referer" ' 
                     '"$http_user_agent" "$http_x_forwarded_for"'; 

   access_log  /var/log/nginx/access.log  main; 

   sendfile        on; 
   #tcp_nopush     on; 

   keepalive_timeout  65; 

   #gzip  on; 

   include /etc/nginx/conf.d/*.conf; 


setup for gunicorn to be run as service.

Description=gunicorn service 

ExecStart=/home/myuser/app1/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/myuser/myproject/myproject.sock myproject.wsgi:application --log-level debug 


don’t forget to enable service using:

systemctl enable gunicorn


import os 

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 

SECRET_KEY = '6sp(_!o*NOT_MY_REAL_KEY_OF_COURSE*uu5o(9q1+ir=:-)r' # change: my key

DEBUG = True # to be changed on production

ALLOWED_HOSTS = ['my_ip',''] #change: my_ip & my domain

# Application definition 

   'myproject.templatetags', # delete:my custom tags
   'login', # delete:my app
   'weeklyreport', # delete:my app

ROOT_URLCONF = 'myproject.urls' 

       'BACKEND': 'django.template.backends.django.DjangoTemplates', 
       'DIRS': ['my_templates'],  #change
       'APP_DIRS': True, 
       'OPTIONS': { 
           'context_processors': [ 

WSGI_APPLICATION = 'myproject.wsgi.application' 

   'default': { #change: my database setup
       'ENGINE': 'django.db.backends.mysql', 
       'NAME': 'mydb1', 
       'USER': 'myuseruser', 
       'PASSWORD': 'my_db_password', 
       'HOST': '', 
       'OPTIONS': { 
           'read_default_file': '/etc/my.cnf.d/client.cnf', 
           'init_command': "SET sql_mode='STRICT_TRANS_TABLES'; SET SESSION binlog_format = 'ROW';", 
        'jgmotordb': { #delete: my database setup
       'ENGINE': 'django.db.backends.mysql', 
       'NAME': 'mydb2',  #change
       'USER': 'myuseruser', #change
       'PASSWORD': 'my_db_password',  #change
       'HOST': 'my_ip', # change
       'OPTIONS': { 
           'read_default_file': '/etc/my.cnf.d/client.cnf', 
           'init_command': "SET sql_mode='STRICT_TRANS_TABLES'; SET SESSION binlog_format = 'ROW';", 

       'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 
       'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 
       'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 
       'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 

LANGUAGE_CODE = 'en-us' 
USE_I18N = True 
USE_L10N = True 
USE_TZ = True 

STATIC_URL = '/static/' # my static folder
   os.path.join(BASE_DIR, '0static'),  # my static folder (before for 'collectstatic' command)
STATIC_ROOT = os.path.join(BASE_DIR, 'static') 
AUTHENTICATION_BACKENDS = ( 'myproject.backend.custombackend', ) #delete: my custom backends

It’s my django project. Therefor, you might find my setup is not ideal, but it works! ūüôā (and it took me a week to make it works).

I learn that, most of tutorials use apt /¬†apt-get for installation. Since I use CenOS (which use yum as default) I find it annoying. ūüė¶

Please leave a comment for any suggestion or if you find this post helpful.