How to Deploy Django Channels by configuring Nginx to run both Gunicorn and Daphne

Dec. 2, 2022


0
5 min read
464

Django Channels enables a developer to use WebSockets and other non-HTTP protocols in any Django project. By, using non-HTTP protocol the website can receive real-time updates from the server. The most common use case for Django Channels would be when we want to implement a chat application. Chat applications need to be real-time and seamless and that is where Django channels offer great benefits over using traditional Ajax-based request-response chat models. Unfortunately, new developers might find Django channels both hard to implement and difficult to deploy. Luckily, its official documentation covers a great tutorial on implementation which I will be linking below. Django channels require ASGI (Asynchronous Server Gateway Interface) for deployment. We will be using Daphne for ASGI. WSGI (Web Server Gateway Interface) will be used for the rest of the project deployment. For WSGI, Gunicorn will be used. The tutorial is of an intermediate level and some prerequisite tutorial needs to be followed beforehand.

Deployment of both WSGI and ASGI using Nginx and Supervisor

What is Nginx? A high-performance free open-source web server powering the busiest sites on the Internet. nginx [engine x] is an HTTP and reverse proxy server, as well as a mail proxy server, written by Igor Sysoev. According to Netcraft Nginx served or proxied 30.46% of the top million busiest sites in Jan 2018. Find out more here: https://nginx.org/

What is Supervisor? The supervisor is a process control system that allows you to monitor and provide resources for different UNIX processes (which makes sense in our case since we need to run our Daphne server as a separate process so that it can handle our Websocket connections seamlessly). Find out more here: http://supervisord.org/

What is Gunicorn? A Python WSGI HTTP Server for UNIX. Gunicorn is a pre-fork worker model ported from Ruby's Unicorn project. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resources, and fairly speedy. Find out more here: https://gunicorn.org/

What is Daphne? Daphne is an HTTP, HTTP2 and WebSocket protocol server for ASGI and ASGI-HTTP developed to power Django Channels. It supports the automatic negotiation of protocols; there's no need for URL prefixing to determine WebSocket endpoints versus HTTP endpoints.

This tutorial mostly follows the official documentation with some modifications.

Replace the projects asgi.py file content with this: 

import os
from django.conf.urls import url
 
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_examples.settings')
 
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
django_asgi_app = get_asgi_application()
 
from channels.auth import AuthMiddlewareStack   
import chat.routing
 
 
application = ProtocolTypeRouter({
    "http": django_asgi_app,
    'websocket': AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    )
})

Since Nginx should be already installed in the first prerequisite we only need to install Supervisor.

$ sudo apt install supervisor

Let us now make a config file called channels.conf inside /etc/supervisor/conf.d/ -The supervisor will listen on a TCP port and then pass the socket to the child process for further processing. The file will contain this:

[fcgi-program:asgi]
# TCP socket used by Nginx backend upstream
socket=tcp://localhost:8000
 
# Directory where your site's project files are located
directory=/home/saif/django_examples
 
# Each process needs to have a separate socket file, so we use process_num
# Make sure to update "django_examples.asgi" to match your project name
command=/home/saif/django_examples/djangovirtualenv/bin/daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers django_examples.asgi:application
 
# Number of processes to startup, roughly the number of CPUs you have
numprocs=4
 
# Give each process a unique name so they can be told apart
process_name=asgi%(process_num)d
 
# Automatically start and recover processes
autostart=true
autorestart=true
# Choose where you want your log to go
stdout_logfile=/var/log/asgi.log
redirect_stderr=true

Create the run directory for the sockets referenced in the supervisor configuration file.

$ sudo mkdir /run/daphne/

If the supervisor fcgi-program is being run under a different user make sure to change the owner settings of the run directory.

$ sudo chown <user>.<group> /run/daphne/

On every server reboot, the /run/daphne folder will be cleared out. To make it persistent create a file /usr/lib/tmpfiles.d/daphne.conf and add the following in its content:

$ d /run/daphne 0755 <user> <group>

Make sure the supervisor reread and update itself with the new job:

$ sudo supervisorctl reread
$ sudo supervisorctl update

Next, put the following setting in your Nginx Config file:

upstream ws_server {
    server localhost:8000;
}
 
 
server {
    listen 80;
    server_name 'mywebsite.com';
 
    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/saif/django_examples;
    }
 # WSGI
    location / {
        try_files $uri @proxy_to_app;
    }
# ASGI
    location /ws {
        try_files $uri @proxy_to_ws;
    }
 
    location @proxy_to_ws {
        proxy_pass http://ws_server;
         
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
 
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
    }
 
    location @proxy_to_app {
        include proxy_params;
        proxy_pass   http://unix:/home/saif/django_examples/django_examples.sock;
    }
 
}

Reload Nginx to apply the new changes:

$ sudo service nginx reload

That’s it. Your server should be able to serve both ASGI and WSGI-based apps now. In case you faced some issues. I have followed the official Django Channels tutorial. The tutorial is followed in the chat app. Simply download and deploy it on your local machine.

django Project Deployment Channels Appreciate you stopping by my post! 😊

Add a comment


Note: If you use these tags, write your text inside the HTML tag.
Login Required
Author's profile
Profile Image

Abdulla Fajal

Django Developer

With 'espere.in' under my care, I, Abdulla Fajal, graciously invite your insights and suggestions, as we endeavour to craft an exquisite online experience together.