Django Channels Nginx production

Harry picture Harry · Sep 12, 2017 · Viewed 8.6k times · Source

I have a django project and recently added channels to use websockets. This seems to all work fine, but the problem I have is to get the production ready.

My setup is as follows:

Nginx web server
Gunicorn for django
SSL enabled

Since I have added channels to the mix. I have spent the last day trying to get it to work.

On all the turtotials they say you run daphne on some port then show how to setup nginx for that.

But what about having gunicorn serving django?

So now I have guncorn running this django app on 8001

If I run daphne on another port, lets say 8002 - how should it know its par of this django project? And what about run workers?

Should Gunicorn, Daphne and runworkers all run together?

Answer

Kal picture Kal · Jul 28, 2018

This question is actually addressed in the latest Django Channels docs:

It is good practice to use a common path prefix like /ws/ to distinguish WebSocket connections from ordinary HTTP connections because it will make deploying Channels to a production environment in certain configurations easier.

In particular for large sites it will be possible to configure a production-grade HTTP server like nginx to route requests based on path to either (1) a production-grade WSGI server like Gunicorn+Django for ordinary HTTP requests or (2) a production-grade ASGI server like Daphne+Channels for WebSocket requests.

Note that for smaller sites you can use a simpler deployment strategy where Daphne serves all requests - HTTP and WebSocket - rather than having a separate WSGI server. In this deployment configuration no common path prefix like is /ws/ is necessary.

In practice, your NGINX configuration would then look something like (shortened to only include relevant bits):

upstream daphne_server {
  server unix:/var/www/html/env/run/daphne.sock fail_timeout=0;
}

upstream gunicorn_server {
  server unix:/var/www/html/env/run/gunicorn.sock fail_timeout=0;
}

server { 
  listen   80; 
  server_name _;

  location /ws/ {
    proxy_pass http://daphne_server;
  }

  location / {
    proxy_pass http://gunicorn_server;
  }
}

(Above it is assumed that you are binding the Gunicorn and Daphne servers to Unix socket files.)