How to Host Multiple Django or Python Apps on the Same Host With Nginx and Gunicorn

By | 2014/04/03

It is possible to run multiple Django apps or Python apps on a single host by specifying unique ports for each app in Gunicorn and Nginx. Here are some tips!


This example uses nginx and gunicorn on Debian Wheezy from the Debian repositories.

Install nginx and gunicorn from apt-get:

$ sudo apt-get install nginx gunicorn

First, create individual nginx site files for each site under /etc/nginx/sites-available/

In nginx, server_name is what will connect your browser to the right app or site that is being hosted. Also note that you must use a unique port number on the proxy_pass line for each django site or python app running on the host.

/etc/nginx/sites-available/example.com

server {
    listen 80;
    server_name example.com;
    access_log  /var/log/nginx/access.log;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

}


/etc/nginx/sites-available/example2.com

server {
    listen 80;
    server_name example2.com;
    access_log  /var/log/nginx/access.log;

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

}

To enable these sites for nginx, create a symlink to /etc/nginx/sites-enabled/ for each site.

$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

Next, make a gunicorn config file for each site under /etc/gunicorn.d/ on Debian. Make sure the file ends with .conf. Note that the port number must match to the port number specified in your nginx config for each site.

Note: for these I have a file /var/www/example.com/wsgi-app.py as my wsgi script.

/etc/gunicorn.d/example.com.conf

CONFIG = {
    'mode': 'wsgi',
    'working_dir': '/var/www/example.com',
      'python': '/var/www/example.com/virtualenv/bin/python',
    'args': (
        '--bind=127.0.0.1:8000',
        '--workers=4',
        '--timeout=260',
        '--max-requests=500',
        'wsgi-app',
    ),
}


/etc/gunicorn.d/example2.com.conf

CONFIG = {
    'mode': 'wsgi',
    'working_dir': '/var/www/example2.com',
      'python': '/var/www/example2.com/virtualenv/bin/python',
    'args': (
        '--bind=127.0.0.1:8001',
        '--workers=4',
        '--timeout=260',
        '--max-requests=500',
        'wsgi-app',
    ),
}

When ready, start gunicorn, then nginx.

$ sudo /etc/init.d/gunicorn start

$ sudo /etc/init.d/nginx start

Host additional sites by using additional port numbers!

Problems? To get debugging info from gunicorn, consider temporarily enabling debug logging. On Debian, gunicorn logs to /var/log/gunicorn/ .

CONFIG = {
    'mode': 'wsgi',
    'working_dir': '/var/www/example.com',
      'python': '/var/www/example.com/virtualenv/bin/python',
    'args': (
        '--bind=127.0.0.1:8000',
        '--workers=4',
        '--timeout=260',
        '--max-requests=500',
        'wsgi-app',
        '--debug',
        '--log-level=debug',
    ),
}

4 thoughts on “How to Host Multiple Django or Python Apps on the Same Host With Nginx and Gunicorn

  1. Prajjwal

    Hi Scott,
    I have a doubt.
    What is that wsgi-app or wsgi script ?
    Quoting you –
    “Note: for these I have a file /var/www/example.com/wsgi-app.py as my wsgi script.
    and this wsgi-app appears in the .conf file too.”

    I am new to these configurations so please pardon me if it is too silly, but do answer me.. Thanks

    Reply
    1. Scott Miller Post author

      The wsgi file can vary wildly depending on the app, the environment, and other things. Here is one I use from a django site:

      import site
      import os
      
      ve_path = '/var/www/example.com/virtualenv'
      
      site.addsitedir(os.path.join(ve_path, 'project'))
      site.addsitedir(os.path.join(ve_path, 'lib/python2.7/site-packages'))
      
      # adds code in 'src' to sitedirs
      src_path = os.path.join(ve_path, 'src')
      if os.path.isdir(src_path):
          for entry in os.listdir(src_path):
              entry_path = os.path.join(src_path, entry)
              if os.path.isdir(entry_path):
                  site.addsitedir(entry_path)
      
      os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
      
      
      from django.core.wsgi import get_wsgi_application
      application = get_wsgi_application()
      
      Reply
  2. arif

    Thanks for your post,
    Mybe, We also can use docker to run multiple apps Each apps run on container wich each depedencies. And use nginx as reverse proxy.

    Reply

Leave a Reply

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

Notify me of followup comments via e-mail. You can also subscribe without commenting.