Websocket 502 Bad Gateway - django

I've two container wsgi and asgi.
wsgi server is running on 127.0.0.8000:
gunicorn app.wsgi:application --bind 127.0.0.1:8000
Also asgi server is running on 127.0.0.1:8001 using of daphne:
daphne -b 127.0.0.1 -p 8001 app.asgi:application
I have a websocket request like this:
wss://app.example.com/ws/chat/f770eef/
But unfortunately these errors occur in the system:
i) nginx log says:
2022/05/22 13:15:29 [error] 463129#463129: *9 upstream prematurely
closed connection while reading response header from upstream, client:
11.198.111.11, server: app.example.com, request: "GET /ws/chat/f770eef/
ii) Requests do not reach daphne.
asgi.py
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
application = get_asgi_application()
nginx cofing:
server {
listen 443;
listen [::]:443;
server_name app.example.com;
root /var/www/html;
...
location /ws/ {
proxy_pass http://127.0.0.1:8001;
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;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
}
...
}

I had the same problem with my setup. changing the the proxy_pass setting to HTTPS instead of http fixed it for me.
...
proxy_pass https://127.0.0.1:8001;
...
Since you're using WSS, thats WS over SSL protocol so HTTP doesn't cut it and I guess Nginx or some other service terminates the connection

Related

Why does my websocket keep disconnecting in Django Channels App?

I have been on this for a month now without a working solution. Everything works fine in production but I have been trying to deploy my django-channels application using nginx as reverse proxy, supervisor to keep servers running, gunicorn to serve http requests and I am stuck at the weboscket request part using daphne to process http requests.
I am bindig with unix sockets: gunicorn.sock and daphne.sock
The Console returns:
WebSocket connection to 'ws://theminglemarket.com/ws/chat/undefined/' failed:
Error during WebSocket handshake: Unexpected response code: 500
My supervisor config:
directory=/home/path/to/src
command=/home/path/to/venv/bin/gunicorn_start
user=root
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/path/to/log/gunicorn/gunicorn-error.log
[program:serverinterface]
directory=/home/path/to/src
command=/home/path/to/venv/bin/daphne -u /var/run/daphne.sock chat.asgi:application
autostart=true
autorestart=true
stopasgroup=true
user=root
stdout_logfile = /path/to/log/gunicorn/daphne-error.log
Redis server is up and Running, Sure of that, using redis-server
my nginx configurations:
upstream channels-backend {
# server 0.0.0.0:8001;
server unix:/var/run/daphne.sock fail_timeout=0;
}
upstream app_server {
server unix:/var/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
server_name theminglemarket.com www.theminglemarket.com;
keepalive_timeout 5;
client_max_body_size 4G;
access_log /home/path/to/logs/nginx-access.log;
error_log /home/path/to/logs/nginx-error.log;
location /static/ {
alias /home/path/to/src/static/;
# try_files $uri $uri/ =404;
}
location / {
try_files $uri #proxy_to_app;
}
location /ws/ {
try_files $uri #proxy_to_ws;
}
location #proxy_to_ws {
proxy_pass http://channels-backend;
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 {
proxy_pass http://app_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
}
}
Please ask for any other thing needed, I'll update as quickly as I can. Thank You.
It's a chatting application, do you think I should use only Daphne, I'm considering the scalability, and that's why I used gunicorn to serve http requests. Hosting on Ubuntu Server
Try putting socket=tcp://0.0.0.0:8001 or socket=tcp://localhost:8001 in your [program:serverinterface] part of supervisord.conf. After that read your supervisor_log.log file to find out how it behaves. I had similar problems with it too. I hope that this helps. Use socket=tcp://localhost:8001 if it's inside of docker container. And make sure that nginx container is on the same docker network as that container.

Django Channels doesn't detect WebSocket request with NGINX

I am deploying a website on AWS. Everything works fine for HTTP and HTTPS. I am passing all requests to Daphne. However, incoming WebSocket connections are treated as HTTP requests by Django. I am guessing there is some header that isn't set in Nginx, but I have copied a lot of my Nginx config from tutorials.
Nginx Config:
upstream django {
server 127.0.0.1:9000;
}
server {
listen 80;
server_name 18.130.130.126;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name 18.130.130.126;
ssl_certificate /etc/nginx/certificate/certificate.crt;
ssl_certificate_key /etc/nginx/certificate/private.key;
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 / {
include proxy_params;
proxy_pass http://django;
}
}
Daphne is bonded to 0.0.0.0:9000. Channels have a very basic setup. A ProtocolTypeRouter, with AuthMiddlewareStack and then URLRouter, as shown on the Channels tutorial. And then a Consumer class. I am using Redis for the channel layer, but that doesn't seem to be a problem. This is some data about the request on response from fiddler. The request headers say Upgrade to WebSocket, but it returns a 404 HTTP request, as it doesn't see it as a WebSocket request.
Thanks for any help.
include proxy params was the problem. It was overwriting headers.

Getting rid of port in URL for django installation in production

I'm trying for the first time to deploy my Django application on a server but so far I wasn't able to get rid of port in my URL. Right now I'm using Gunicorn with Nginx with the following configuration.
Nginx /etc/nginx/sites-enabled/site.conf
server {
listen 8000;
server_name example.com;
location = /favicon.ico {access_log off;log_not_found off;}
location /static/ {
root /home/webapp/um;
}
location /media/ {
root /home/webapp/um;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/webapp/um/um.sock;
}
}
/etc/nginx/proxy_params
proxy_set_header Host $http_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-Proto $scheme;
Gunicorn /etc/systemd/system/gunicorn.service
Description=gunicorn service
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/home/webapp/um/
ExecStart=/root/um/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/webapp/um/um.sock um.wsgi:application
[Install]
WantedBy=multi-user.target
Gunicorn binding
gunicorn --bind 0.0.0.0:8000 um.wsgi:application
Changing port 8000 with port 80 in /etc/nginx/sites-enabled/site.conf gives me a 404 on nginx. Using port 8000 I'm able to see the site using http://example.com:8000/myapp but I'm aiming at using http://example.com/myapp as my address.
As a side note, the VPS I'm installing the app on came with Plesk already installed with which I'm also not familiar with. I don't know if Plesk might be interferring in catching traffic from port 80.
Thanks in advance
You just need to listen this server on port 80 instead of 8000
save gunicorn as described
server {
listen 80;
server_name 52.14.64.58 example.com www.example.com;
location = /favicon.ico {access_log off;log_not_found off;}
location /static/ {
root /home/webapp/um;
}
location /media/ {
root /home/webapp/um;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/webapp/um/um.sock;
}
}
52.14.64.58 => is ipv4 of your virtual machine, it could be anything in your case.
Now time to make changes in our django settings
ALLOWED_HOSTS = ['IP_ADDRESS', 'example.com', 'www.example.com']
Now check nginx status then restart gunicorn and nginx . I hope it would work for you.
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl restart gunicorn
Now setup your domain by it's dns settings.
After a bit of struggling, I found the solution. Turns out my config was correct, but there was an nginx config file automatically written by plesk that was catching requests on port 80. The content of such file is
server {
listen 111.111.111.111:80;
location ^~ /plesk-site-preview/ {
proxy_pass http://127.0.0.1:8880;
proxy_set_header Host plesk-site-preview.local;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cookie_domain plesk-site-preview.local $host;
access_log off;
}
location / {
proxy_pass http://111.111.111.111:7080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 111.111.111.111:443 ssl;
ssl_certificate /opt/psa/var/certificates/certWpPLaPv;
ssl_certificate_key /opt/psa/var/certificates/certWpPLaPv;
location ^~ /plesk-site-preview/ {
proxy_pass http://127.0.0.1:8880;
proxy_set_header Host plesk-site-preview.local;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cookie_domain plesk-site-preview.local $host;
access_log off;
}
location / {
proxy_pass https://111.111.111.111:7081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Once I removed that file from inclusion in nginx.conf everything started working. As a suggestion for whoever is facing a similar situation, I would recommend to check what Nginx is processing using the following command
nginx -T

Possible to serve Django Channels app only using Nginx and Daphne?

I was under the assumption that I could run a Django Channels app using only Daphne (ASGI) and Nginx as a proxy for my Django app to begin with.
The application would be running with Daphne on 127.0.0.1:8001
However, I am running into a 403 Forbidden error.
2019/03/06 17:45:40 [error] *1 directory index of "/home/user1/app/src/app/" is forbidden
And when I posted about that, another user mentioned
There is no directive to pass http request to django app in your
nginx config
And suggested to look into fastcgi_pass or uwsgi_pass or Gunicorn.
Obviously Django Channels runs on ASGI and I am passing all requests through that right now (not to uWSGI then on to ASGI depending on the request.)
Can I serve my Django app with only Nginx and Daphne? The Django Channels docs seem to think so as they don't mention needing Gunicorn or something similar.
my nginx config
upstream socket {
ip_hash;
server 127.0.0.1:8001 fail_timeout=0;
}
server {
listen 80;
#listen [::]:80 ipv6only=on;
server_name your.server.com;
access_log /etc/nginx/access.log;
root /var/www/html/someroot;
location / {
#autoindex on;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri =404;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header Host $http_host;
#proxy_set_header X-NginX-Proxy true;
#proxy_pass http://socket;
#proxy_redirect off;
#proxy_http_version 1.1;
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
#proxy_redirect off;
#proxy_set_header X-Forwarded-Proto $scheme;
#proxy_cache one;
#proxy_cache_key sfs$request_uri$scheme;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/some/fullchain.pem;
# managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/some/privkey.pem;
# managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
Yes, it's possible. Try this config:
upstream socket {
ip_hash;
server $DAPHNE_IP_ADDRESS$ fail_timeout=0;
}
server {
...
location / {
proxy_pass http://socket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
...
}
Where $DAPHNE_IP_ADDRESS$ - your daphne IP and port without schema(127.0.0.1:8001).

How can I use django's built-in server behind nginx?

I'm developing with apache2 ( mpm-worker ) + mod_wsgi behind nginx which is silly since I have to sudo apache2ctl graceful for every update I make in anything but the template files.
My nginx conf is:
server {
listen 80;
server_name site.org;
access_log /www/site.org/log/access.log;
error_log /www/site.org/log/error.log;
location / {
proxy_pass http://127.0.0.1:8080/;
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-Magic-Header "secret";
client_max_body_size 10m;
}
}
Would it be a matter of just binding proxy_pass to 127.0.0.1:3000 if 3000 is the port used by the django server?
Ack, didn't realize it was this easy... I..
copied the server {} settings into another file
changed the port to 3001
changed the server name to dev.site.org
updated my host records in the DNS to point to my server IP
restarted nginx
did manage.py runserver 3001.
All is well :)