I'm currently running a Django (2.0.2) server with uWSGI having 10 workers
I'm trying to implement a real time chat and I took a look at Channel.
The documentation mentions that the server needs to be run with Daphne, and Daphne needs an asynchronous version of UWSGI named ASGI.
I manged to install and setup ASGI and then run the server with daphne but with only one worker (a limitation of ASGI as I understood) but the load it too high for the worker.
Is it possible to run the server with uWSGI with 10 workers to reply to HTTP/HTTPS requests and use ASGI/Daphne for WS/WSS (WebSocket) requests ?
Or maybe it's possible to run multiples instances of ASGI ?
It is possible to run WSGI alongside ASGI here is an example of a Nginx configuration:
server {
listen 80;
server_name {{ server_name }};
charset utf-8;
location /static {
alias {{ static_root }};
}
# this is the endpoint of the channels routing
location /ws/ {
proxy_pass http://localhost:8089; # daphne (ASGI) listening on port 8089
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
proxy_pass http://localhost:8088; # gunicorn (WSGI) listening on port 8088
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_connect_timeout 75s;
proxy_read_timeout 300s;
client_max_body_size 50m;
}
}
To use the /ws/ correctly, you will need to enter your URL like that:
ws://localhost/ws/your_path
Then nginx will be able to upgrade the connection.
Related
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.
I have a django app with gunicorn running on port 2333.In nginx.conf I set
server {
listen 80;
server_name mydomain.com;
location / {
proxy_cache my_cache;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2333;
expires 30d;
}
now I can view my django app on address http://ipaddress:2333 and mydomain.com
but I don't want users to view my site by http://ipaddress:2333 .How to allow nginx only use mydomain.com to access my site.
I have tried to use "server default".It not worked.
server {
listen 2333 default;
server_name _;
return 500;
}
Nginx has nothing to do with that. Your Gunicorn (Django) app is listening on port 2333. Therefore, you can bypass nginx by connecting to http://$SERVER:2333. It will work even if you stop nginx.
What you need to do is tell gunicorn to listen only on the localhost, e.g. with --bind=127.0.0.1:2333. Then port 2333 will be accepting connections only from the local network interface.
I got a 502 error when I'm trying to open a website. I used the instructions from the official website link
Added new file lifeline.conf at /etc/supervisor/conf.d/
lifeline.conf
[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/ubuntu/lifeline/lifeline-backend
# Each process needs to have a separate socket file, so we use process_num
# Make sure to update "mysite.asgi" to match your project name
command=/home/ubuntu/Env/lifeline/bin/daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-head$
# 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=/home/ubuntu/asgi.log
redirect_stderr=true
Setup nginx conf
upstream channels-backend {
server localhost:8000;
}
server {
listen 80;
server_name staging.mysite.com www.staging.mysite.com;
client_max_body_size 30M;
location = /favicon.ico { access_log off; log_not_found off; }
location / {
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
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;
}
}
I checked the asgi log file and it contains an error .
daphne: error: the following arguments are required: application
I'm guessing a mistake in lifeline.conf.
I am assuming you are not passing asgi application to daphne, because configuration you pasted in question has missing line. You have to pass it correctly. Assuming you have conf package with asgi.py module inside it containing asgi application instance, you have to do
command=/home/ubuntu/Env/lifeline/bin/daphne -u /run/daphne/daphne%(process_num)d.sock conf.asgi:application
conf.asgi:application should be at the end.
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).
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 :)