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).
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 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.
I have had confirmation in another question that I can indeed run a Django app using only Nginx and Daphne and have modified my nginx config code as per their suggestion.
The application is running with Daphne on 127.0.0.1:8001
However, I am running into a 403 Forbidden error. The nginx error logs say:
"2019/03/07 11:23:48 [error] 16642#16642: *11 directory index of "/path/to/app" is forbidden, client: xx.xxx.xx.xx, server: app.com, request: "GET / HTTP/1.1", host: "www.app.com", referrer: "http://www.app.com""
I'm still facing a 403 and would be grateful to anyone who may be able to locate where the problem is coming from.
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;
}
}
I had to change try_files $uri=404; to try_files $uri $uri/ =404; and that fixed the issue of the main page however other pages still display 404 error.
I am currently working on deploying my project over https however I am running into some issues. I have it working with http but when I try to incorporate the ssl it breaks. I think I am misconfiguring the gunicorn upstream client in my nginx block but I am uncertain. Could the issue be in the unix binding in my gunicorn service file? I am very new to gunicorn so I'm a little lost.
Here is my configuration below.
Gunicorn:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
Environment=PYTHONHASHSEED=random
User=USER
Group=www-data
WorkingDirectory=/path/to/project
ExecStart=/path/to/project/project_env/bin/gunicorn --workers 3 --bind unix:/path/to/project/project.sock project.wsgi:application
[Install]
WantedBy=multi-user.target
Nginx (working-http):
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name server_domain;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /path/to/project;
}
location / {
include proxy_params;
proxy_pass http://unix:/path/to/project/project.sock;
}
}
Nginx (https):
upstream server_prod {
server unix:/path/to/project/project.sock fail_timeout=0;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name server_domain;
}
server {
server_name server_domain;
listen 443;
ssl on;
ssl_certificate /etc/ssl/server_domain.crt;
ssl_certificate_key /etc/ssl/server_domain.key;
location /static/ {
root /path/to/project;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://server_prod;
break;
}
}
}
Your gunicorn systemd unit file seems OK. Your nginx is generally OK too. You have posted too little info to get an appropriate diagnostic. I'm guessing you are missing passing the X-Forwarded-Proto header to gunicorn, but it could be something else. Here's an nginx configuration file that works for me:
upstream gunicorn{
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
# for UNIX domain socket setups:
server unix:/path/to/project/project.sock fail_timeout=0;
# for TCP setups, point these to your backend servers
# server 127.0.0.1:9000 fail_timeout=0;
}
server {
listen 80;
listen 443 ssl http2;
server_name server_domain;
ssl_certificate /etc/ssl/server_domain.crt;
ssl_certificate_key /etc/ssl/server_domain.key;
# path for static files
root /path/to/collectstatic/dir;
location / {
# checks for static file, if not found proxy to app
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When Nginx is handling SSL it is helpful to pass the protocol information
# to Gunicorn. Many web frameworks use this information to generate URLs.
# Without this information, the application may mistakenly generate http
# URLs in https responses, leading to mixed content warnings or broken
# applications. In this case, configure Nginx to pass an appropriate header:
proxy_set_header X-Forwarded-Proto $scheme;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
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;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
proxy_pass http://gunicorn;
}
}
Im trying to setup nginx as a proxy server for my django server and here is my configuration.
For some reason when I send a request to the server http://ipaddress it automatically redirects me to https://ipaddress even though I have included anything to redirect.
I want to disable the redirect to https as its a dev server
upstream app_server {
# For a TCP configuration:
server 127.0.0.1:8000 fail_timeout=0;
}
# configuration of the server
server {
#add_header HTTP_X_FORWARDED_PROTO https;
# the port your site will be served on
listen 80 default_server;
# the domain name it will serve for
charset utf-8;
#server_name localhost;
# max upload size
client_max_body_size 75M; # adjust to taste
location / {
# checks for static file, if not found proxy to app
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}