Having an issue using secure websocket (wss) with django, Nginx, Gunicorn, and daphne. My site is hosted through cloudflare which provides the SSL/TLS certificate. I'm using a linux socket in /run/daphne/daphne.sock, where I gave the user 'ubuntu' ownership of the daphne folder.
The websockets work fine locally when it is not secured. When I tried hosting on my EC2 instance, I get the error-
sockets.js:16 WebSocket connection to 'wss://www.mywebsite.com/ws/sheet/FPIXX8/' failed:
Then it keeps trying to reconnect and fail again. It never sets up an initial connection since I don't get a ping.
Here are a few relevant files and snippets of code-
settings.py
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer', # asgi_redis.RedisChannelLayer ?
'CONFIG': {
'hosts': [('localhost', 6379)],
},
}
}
I think there may be an issue with the 'hosts' but I haven't been able to figure out through tutorials/googling, nor am I sure exactly what it does besides set a port. Since I'm using sockets, I imagine this would need to be different (or maybe it's ignored?) in deployment.
Routing.py (in main project dir)
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import app.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
app.routing.websocket_urlpatterns
)
),
})
Routing.py (in app)
from django.urls import re_path
from django.conf.urls import url
from app import consumers
websocket_urlpatterns = [
re_path(r'ws/sheet/(?P<gameID>\w+)/$', consumers.GameConsumer.as_asgi()),
]
I'm pretty sure neither routing.py files don't cause an issue because I still get redirected properly.
asgi.py
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
application = get_asgi_application()
I haven't touched this file.
Javascript
if (window.location.protocol == 'https:') {
wsProtocol = 'wss://'
} else {wsProtocol = 'ws://'}
updateSocket = new WebSocket(
wsProtocol + window.location.host +
'/ws/sheet/' + game_ID + '/');
This also seems to work fine, since I get redirected and it attempts to connect to proper URL with wss://.
systemd/system/daphne.service
[Unit]
Description=project Daphne Service
After=network.target
[Service]
User=ubuntu
Type=simple
WorkingDirectory=/home/ubuntu/django/project/project
ExecStart=/home/ubuntu/django/project/project/virtualenv/bin/daphne \
-u /run/daphne/daphne.sock \
project.asgi:application
[Install]
WantedBy=multi-user.target
systemd/system/daphne.socket
[Unit]
Description=daphne socket
[Socket]
ListenStream=/run/daphne/daphne.sock
[Install]
WantedBy=sockets.target
nginx
server {
listen 80;
server_name www.mywebsite.com mywebsite.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ubuntu/django/project/project/;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
location /ws/ {
proxy_pass http://unix:/run/daphne/daphne.sock;
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;
}
}
WantedBy=sockets.target
I should probably add running 'sudo nginx -t' to get errors does not return any errors. Running 'sudo journalctl -u daphne' usually would not return errors, but I just checked again and I got another Permission Denied error at '/run/daphne/daphne.sock.lock' which I thought was fixed, so I tried to give permission again. Then, I got a 'Address already in use' for the daphne.sock. So, I restarted all services and now it just says 'Configuring endpoint unix:/run/daphne/daphne.sock' as the latest message, so I don't know if that is good or bad.