nginx reverse proxy to apache mod_wsgi django app - django

Been trying to do this for a while and haven't found something that works.
I have a Django app deployed via Apache & mod_wsgi. Apache listens on port 8080 and everything works fine when I access
example.com:8080
I have Nginx listening on port 80 serving a static site at /.
I'm trying to configure Nginx reverse proxy to Apache (Django) such that when I access example.com/app it should take me to the Django app. This is my configuration so far:
location /app/ {
proxy_pass http://localhost: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;
}
I have tried using/not_using the trail slash both after app and the proxy_pass address.
However, I am always getting a 404 Not Found error.
Can someone please help me to correctly set the reverse proxy in Nginx?
Thanks in advance

FORCE_SCRIPT_NAME='/app/'
Add this at settings.py and restart Django. The value should match locations entry in nginx to work it correctly.

Related

Django + Apache2 behind NGINX reverse proxy - redirections going wrong

I have a Django project running on Apache2 with mod_wsgi in a VM - https://systems3.slt.local/
Accessing the VM directly, via https://systems3.slt.local/ works perfectly. However, I need it to work behind an NGINX reverse proxy, and I'm having problems with login redirection.
My proxy is configured like this:
location /systems3 {
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-Proto $scheme;
proxy_redirect off;
proxy_pass https://systems3.slt.local/;
}
When I try to access the project through the proxy, /systems3, Django checks that there is no user logged in, and then redirects to /accounts/login. The correct would be to redirect to /systems3/accounts/login/. Even if I try to directly access this address, I am redirected to /accounts/login.
It seems that some configuration is missing so that the address /systems3 is the root of the project, it shouldn't be redirecting me outside of systems3.
It's also giving problem with my static folder, it also looks for the folder at /static, ignoring that it was supposed to look inside systems3.

Unable to POST, PUT or DELETE resource with flask when setting up https using nginx and gunicorn

I have build a flask API.
When using it in dev environment like this : http://www.apiexample.com:5000, it works.
But once I set up prod environment using Nginx, Gunicorn with a trusted SSL certificate (and thus port 443), I can't do POST, PUT or DELETE request anymore, I can do only GET request.
Here is what is shown when I try to send any form.
Is it a matter of certificate or nginx/gunicorn server setup?
I found and fix the issue.
In fact, during redirects my flask application was losing the https and redirect to http instead, cause it was not getting X-Forwarded headers from ngninx.
Here is what I added to my nginx configuration :
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;

Redirecting correctly HTTP to HTTPS using Django and Nginx

I'm trying to redirect my website from HTTP to HTTPS and I've succeeded partially doing so. The thing is, when I type mywebsite.fr, I get the name of the service of the container that contains the website's code in my address bar (e.g. Django app/) with a DNS_PROBE_FINISHED_NXDOMAIN error.
Now, I tried the same thing with another Chrome browser of another computer and this time when I type www.mywebsite.fr I get the same result whereas the non-www is correctly redirected to the secure address.
Finally, I tried the exact same process using my smartphone (Brave) with the www and non-www, I get https://djangoapp with an error ERR_NAME_NOT_RESOLVED whereas when I explicitly type https:\\mywebsite, I get no issues.
So here is the NGINX portion that redirects to the HTTPS server:
server {
...
location / {
return 301 https://djangoapp$request_uri;
}
}
This is the location in the HTTPS server that refers to the upstream:
server {
...
location / {
...
proxy_pass http://djangoapp;
}
}
And, this is the service that runs the code:
djangoapp:
build: .
ports:
- "8000:80"
links:
- db
depends_on:
- db
I do not master yet all the intricacies of NGINX and I do not really understand what I'm doing wrong here. Any solution or pieces of advice on this issue I'm having?
You are returning your django app url instead of redirecting it to your http nginx block.
In your http part of config:
server {
return 301 https://$host$request_uri;
listen 80;
}
And in https, when proxy passing if you dont want the url to change to the url of your django app, you should add proxy_set_header Host $http_host;. It's also useful to add some additional headers like ip address. So the overal server block will look like:
server {
location / {
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;
proxy_pass http://djangoapp;
}
}
My problem was resolved because my proxy_set_header X-Forwarded-Proto was set to $https instead of https. Using $scheme as suggested also works fine.
By reading #mehrad's comment and searching a little bit on the web again, I found the bug on why the redirection was not working properly. This also includes using $host as opposed to djangoapp.

Django Rest framework swagger base url

I have successfully running my rest framework swagger on localhost..
These was my rest framework swagger localhost screenshoot. It has run successfully.
Now i want to deploy it on server testing.
These is the screenshot result of my testing deployment.
As you can see the base path changed and served from localhost, the schemes read the right configuration which is https schemes, and the application run in the right domain which is api.executivemafia.com, so that's not problem. The problem come when I want to try the API. The server point is localhost. So it's make my endpoint request become 'https://127.0.0.1:8000/instagram/hello".
My questions are:
Why the rest framework swagger still read localhost although my application already served in https://api.executivemafia.com/docs/?
Fyi, I set the proxy pass nginx to locahost:8000 because my gunicorn run on localhost:8000.
Can the base url rest framework swagger testing server using my testing server domain end point ? If it's able to, how to do it?
Any help and reference will be appreciated.
Thank you Guys!!
Regards,
Meikelwis Wijaya
Set the following inside the nginx configuration file:
server{
........
location /{
proxy_pass http://yourhostname:port;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
}
it worked for me !!

Nginx does not forwards remote address to gunicorn

I have the following nginx configuration to forward requests to gunicorn.
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
However, when I access remote address using request.META['REMOTE_ADDR'], it always returns 127.0.0.1. I am using Django 1.9
That is correct and expected behavior. If you would like to access users IP you will need to use:
request.META['HTTP_X_FORWARDED_FOR']
Note that in development (without running nginx), REMOTE_ADDR is still correct.
My recommendation is to add a middleware or a utility method which will do the conditional logic to get the actual users IP depending on your settings.