Issues adding Nginx/SSL to *working* Django / Channels / ASGI / Daphne chat app.... Especially how debug WebSocket error msgs?

I’m trying to add Nginx and SSL to a working Django chat app that uses Daphne, Django Channels and ASGI.

I have a page that now tries to make secure (now uses wss:// instead of ws://) WebSocket
connections now and it gives an error…

Here is the Javascript line in my Django view throwing the error:

ws    = new WebSocket(`wss://${window.location.host}/ws/chat/${room_}/`);

Here is the error I see in the Chrome client:

WebSocket connection to 'wss://bighelp.business/ws/chat/test/' failed: 
(anonymous)	@	test/:113

Chrome says the attempted wss://bighelp.business/ws/chat/test/ connection
had to no response headers but just this “provisional” request header:

accept-encoding
gzip, deflate, br, zstd
accept-language
en-US,en;q=0.9
cache-control
no-cache
connection
Upgrade
cookie
sessionid=vlfxucerg3komutbvj7qjdbtouz86cjh; csrftoken=9lpSZQnrXdbZ2WxvwK5BTlzZABs8sGxJatToy7O9e5vVEqrcMYErj6HwaZ5m3jGx
dnt
1
host
bighelp.business
origin
https://bighelp.business
pragma
no-cache
sec-gpc
1
sec-websocket-extensions
permessage-deflate; client_max_window_bits
sec-websocket-key
UhqdwiXDVP/iWXOGa++tJg==
sec-websocket-version
13
upgrade
websocket
user-agent
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36

Here is the error msg I see in Nginx’s error.log:

2025/06/03 16:28:10 [error] 2980116#2980116: *445 upstream prematurely closed connection while reading response header from upstream, client: 98.96.117.129, server: ~^(www\.)?bighelp.business$, request: "GET /ws/chat/test/ HTTP/1.1", upstream: "http://127.0.0.1:8008/ws/chat/test/", host: "bighelp.business"

Here is the Nginx config snippet for this Django app at localhost:8008 …

server {
        server_name          ~^(www\.)?bighelp\.business$;
        listen               80;
        client_max_body_size 100M;
        return               301 https://bighelp.business$request_uri;
}

server {
        server_name          ~^(www\.)?bighelp.business$;
        listen               443 ssl http2;
        client_max_body_size 100M;
        ssl_certificate      /etc/letsencrypt/live/bighelp.business/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/bighelp.business/privkey.pem;
        root                 /home/var/www/bighelp;

        location /sw.js {
                alias /home/var/www/bighelp/static/js/sw.js;
        }

        location /static {
        }

        location /ws/ {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_redirect off;
                proxy_pass http://127.0.0.1:8008;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }

        location / {
                include    /etc/nginx/uwsgi_params;
                uwsgi_pass localhost:8008;
        }
}

============

Any help greatly appreciated.

Sincerely,

Chris

I believe the problem here is that you have 2 server blocks with the same server_name. I’m pretty sure that all requests will be routed to the first defined block, and since it is not listening to port 443, it’s not going to respond to the wss request. I suggest you remove that first server block.

See How nginx processes a request and Server names for more details.

Ken

Thanks. I removed the port 80 server block that routes everything to port 443. Now my Nginx config just has one server block as you suggested but I get the same error. Here is what is left…

server {
        server_name          ~^(www\.)?bighelp.business$;
        listen               443 ssl http2;
        client_max_body_size 100M;
        ssl_certificate      /etc/letsencrypt/live/bighelp.business/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/bighelp.business/privkey.pem;
        root                 /home/var/www/bighelp;

        location /sw.js {
                alias /home/var/www/bighelp/static/js/sw.js;
        }

        location /static {
        }

        location /ws/ {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_redirect off;
                proxy_pass http://127.0.0.1:8008;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }

        location / {
                include    /etc/nginx/uwsgi_params;
                uwsgi_pass localhost:8008;
        }
}

server {
server_name ~^(www.)?bighelp.business$;
listen 443 ssl http2;
client_max_body_size 100M;
ssl_certificate /etc/letsencrypt/live/bighelp.business/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bighelp.business/privkey.pem;
root /home/var/www/bighelp;

    location /sw.js {
            alias /home/var/www/bighelp/static/js/sw.js;
    }

    location /static {
    }

    location /ws/ {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_redirect off;
            proxy_pass http://127.0.0.1:8008;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
    }

    location / {
            include    /etc/nginx/uwsgi_params;
            uwsgi_pass localhost:8008;
    }

}
server {
server_name ~^(www.)?bighelp.business$;
listen 443 ssl http2;
client_max_body_size 100M;
ssl_certificate /etc/letsencrypt/live/bighelp.business/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bighelp.business/privkey.pem;
root /home/var/www/bighelp;

    location /sw.js {
            alias /home/var/www/bighelp/static/js/sw.js;
    }

    location /static {
    }

    location /ws/ {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_redirect off;
            proxy_pass http://127.0.0.1:8008;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
    }

    location / {
            include    /etc/nginx/uwsgi_params;
            uwsgi_pass localhost:8008;
    }

}

Check your nginx logs and syslog for any more detailed information. Also, please post the command line you’re using to run Daphne and your asgi.py file.

Ken

I’m glad you asked about that. I just specify the asgi file, daphne and channel apps in settings.py. I never explicitly launch the daphne server. When I wrote my prototype with no security, I just did

./manage.py runserver

And everything worked. Are you staying with Nginx or SSL added that I have to explicitly launch Daphne now when I didn’t have to before?

Thanks

Quoting directly from the docs for runserver:

Warning
DO NOT USE THIS SERVER IN A PRODUCTION SETTING.

Yes, you need to run Daphne - nginx won’t start it for you.

Ken

It worked when I started daphne! Thanks so much!
I’ve noticed the chat WebSocket connections die
after a few minutes. Is it possible to keep them
open for hours and even days and weeks?

Thanks,

Chris

Or months even. (It may also be useful and sufficient to add some “auto-reconnect” code to your JavaScript.)

There is no “intrinsic” timeout with a websocket per se. It would be something within the configuration of any of your JavaScript, nginx, Daphne, firewall, load-balancer, etc. (It also makes a difference if you’re talking about wired ethernet vs WiFi or cellular connection.)

Finding out the root cause may involve a deep-dive into the network traffic between the endpoints to see which side terminates the connection, and checking logs for appropriate logs for timeout messages. (You may also need to set the log levels to DEBUG for the server components.)