How do I configure nginx with backend and frontend? - django

I have a simple vue.js and django (as REST API) application that I want to combine with nginx. Currently the frontend is working, but the backend is not. Here's my nginx config:
server {
listen 80;
location / {
root /usr/share/nginx/html/;
index index.html index.htm;
}
location /api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:8000/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
Visiting localhost works for the static files, but localhost/api leads to a bad gateway error:
[error] 29#29: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: , request: "GET /api HTTP/1.1", upstream: "http://127.0.0.1:8000/", host: "localhost"
Also, trying to visit localhost/api via the frontend (axios) just returns the 'You need javascript to display this page' site, which is just part of the frontend.
Running the backend seperately, outside of docker and nginx, works fine on localhost:8000.
What can I do to make it work? It doesn't necessarily have to be done this way, as long as the frontend and backend can communicate.

You said you running Docker? Then you need to change localhost to the container name that running your backend.

Related

nginx alias : how to alias on one proxy server only?

I'm trying to get working a single page application with django/wagtail and react.
But at the moment I'm serving django content via restframework and the request on media/ and djangostatic/ are not working.
I have configured nginx to serve /media and /djangostatic to alias /app/media and /app/static but this is not working properly.
Here is the nginx.conf file:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://172.20.128.3:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 20M;
}
location /wagtail {
proxy_pass http://172.20.128.2:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Script-Name /wagtail;
client_max_body_size 20M;
}
location /djangostatic/ {
alias /app/static/;
}
location /media/ {
alias /app/media/;
}
}
When a page in need of /djangostatic is queried, I get the error :
2022/06/12 08:30:10 [error] 22#22: *2 open() "/app/static/wagtailadmin/js/vendor/jquery.datetimepicker.js" failed (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET /djangostatic/wagtailadmin/js/vendor/jquery.datetimepicker.js?v=021047c1 HTTP/1.1", host: "localhost", referrer: "http://localhost/wagtail/cms-admin/login/?next=/wagtail/cms-admin/"
So the alias seems to work (it is replaced by /app/media) but it doesn't open the file. I have checked the backend server container and the file exists.
So my question is simple : the /app/static and /media folders are on http://172.20.128.2:8000, which is the reverse proxy of /wagtail location. How to make the alias working on the /wagtail location proxy server but not on others?
I could make two servers with different names but I want this to work on the same server with reverse proxy serving the backend and frontend.

Websocket 502 Bad Gateway

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

400 Handshake Error With Application Load Balancer AWS (Flask & Socket.io)

Getting a 400 handshake error on POST requests to my Flask app running socket.io, but I've added in the configs for NGINX according to docs and posts I read online. I'm using an Application Load Balancer in AWS and have set a :80 Target Group and a :443 listener which forwards to the Target Group. I have also added a rule for the route /socket.io to forward request to the target group on :80 and have enabled sticky sessions within the target group. I'm also using a Route53 domain name and enforcing SSL everything works fine except the socket communication.
NGINX conf file:
server {
listen [::]:80;
listen 80;
server_name _domain_name_;
access_log /var/log/nginx/access.log;
location / {
proxy_pass http://127.0.0.1:8000;
include proxy_params;
}
location /socket.io {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
include proxy_params;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:8000/socket.io;
}
}
And js file connection for socket.io:
var socket = io();
socket.on('connect', () => {
console.log(socket.connected); // true
});
Connection returns true.
Listener Rule
UPDATE
Switched to NLB and am still having the same issues, however now on my NGINX logs I am seeing
connect() failed (111: Connection refused) while connecting to upstream
request: "GET /socket.io/?EIO=3&transport=polling&t=MvDPJhb HTTP/1.1",
upstream: "http://127.0.0.1:8000/socket.io/?
EIO=3&transport=polling&t=MvDPJhb"

Does Django Channels uses ws:// protocol prefix to route between Django view or Channels app?

I am running Django + Channels server using Daphne. Daphne server is behind Nginx. My Nginx config looks like as given at end.
When I try to connect to ws://example.com/ws/endpoint I am getting NOT FOUNT /ws/endpoint error.
For me, it looks like Daphne is using protocol to route to either Django views or Channels app. If it sees http it routes to Django view and when it sees ws it routes to Channels app.
With following Nginx proxy pass configuration the URL always has http protocol prefix. So I am getting 404 or NOT FOUND in logs. If I change proxy_pass prefix to ws Nginx config fails.
What is the ideal way to setup Channels in the this scenario?
server {
listen 443 ssl;
server_name example.com
location / {
# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
# redirect all HTTP traffic to localhost:8088;
proxy_pass http://0.0.0.0:8000/;
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_set_header X-NginX-Proxy true;
# enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 999999999;
}
}
Yes, as in the question Channels detects the route based on the protocol header ws or http/https
Using ws prefix in proxy_pass http://0.0.0.0:8000/; is not possible. To forward the protocol information following config should be included.
proxy_set_header X-Forwarded-Proto $scheme;
This will forward the schema/protocol(ws) information to Channels app. And channels routes according to this information.

Getting 404 not found when working with docker container nginx uwsgi django

I'm having 3 docker containers.
One container has Django with uwsgi and nginx as webserver. I configure inside with 80 port exposed. And later run with 8800:80 mapping in my localhost.
A second container has another Django project with uwsgi and nginx, similar configuration and run with 8801:80 mapping in my localhost.
So right now I can access different Django apps from the container with different ports.
localhost:8800 -> app1
localhost:8801 -> app2
now I create a third container with nginx, which aims to do the reverse proxy.
So I third container has only nginx configuration. Which has something like this:
error_log /var/log/nginx/error.log;
events {
worker_connections 1024;
}
http {
sendfile on;
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/xml text/css
text/comma-separated-values
text/javascript
application/x-javascript
application/atom+xml;
upstream app1{
server my_machine_ip:8800;
}
upstream app2{
server my_machine_ip:8801;
}
access_log /var/log/nginx/access.log;
server {
listen 0.0.0.0:80;
location /firstapp/ {
proxy_pass http://app1/;
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 /anotherapp/ {
proxy_pass http://app2/;
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;
}
}
}
Again the container with 80 port expose and I run with port 8888:80 mappings.
Then I have some problems:
When I type localhost:8888/firstapp/, it shows 404 not found. But the URL change to localhost:8888/base/auth/login/?next=/ which it is the login page URL of app1. When I curl with localhost it actually gives my feed back that it is doing the redirection. But the browser just return me a 404 page and I can't login to the project. However, when I type localhost:8800 I can see the login page and login perfectly. It looks like the nginx reverse proxy needs to know the static files to function correctly. So my question:
How the nginx reverse proxy processing the request? My understanding that my current configuration is look like this:
web client <-> nginx reverse proxy <-> nginx webserver <-> uwsgi <-> Django project
My testing of
web client <-> nginx webserver <-> uwsgi <-> Django project
of this chain is totally fine. But when I added the nginx reverse proxy in the chain, then I got the 404 error.
So far as my understanding of this 404 error, I want to know that whether the nginx reverse proxy needs to know where the static files locate in order to function properly. Or I miss something or understanding in configuration.
My goal is to use make different Django projects on the same machine, with same configurations(port 80, so that different projects group can follow the same pattern), and use reverse proxy to type different URI to access different projects.
HTTP/1.1 302 Found
Server: nginx/1.13.5
Date: Tue, 17 Oct 2017 14:39:42 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
X-Frame-Options: DENY
Location: /base/auth/login/?next=/
Vary: Cookie