Django Rest framework swagger base url - django

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 !!

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;

localhost in build_absolute_uri for Django with Nginx

On production I use the chain Django - UWSGI - Docker - Nxing. UWSGI works with the port 50012 and Ngxin is configured as:
proxy_pass http://localhost:50012;
Django process thinks that its host is localhost:50012 instead of the domain that Nginx listens to. So when the function build_absolute_uri is called there's localhost:50012 instead of my domain. Is there a way to make Django use the custom host name when build_absolute_uri is called?
Notice: in some libraries build_absolute_uri called implicitly (like social-django, or example), so avoiding this function is not a solution in my case.
The problem
When the public hostname you use to reach the proxy differ from the internal hostname of the application server, Django has no way to know which hostname was used in the original request unless the proxy is passing this information along.
Possible Solutions
1) Set the proxy to pass along the orginal host
From MDN:
The X-Forwarded-Host (XFH) header is a de-facto standard header for identifying the original host requested by the client in the Host HTTP request header.
Host names and ports of reverse proxies (load balancers, CDNs) may differ from the origin server handling the request, in that case the X-Forwarded-Host header is useful to determine which Host was originally used.
There are two things you should do:
ensure all proxies in front of Django are passing along the X-Forwarded-Host header
turn on USE_X_FORWARDED_HOST in the settings
if the internal and external scheme differ as well, set SECURE_PROXY_SSL_HEADER to a meaningful value and set the server to send the corresponding header
When USE_X_FORWARDED_HOST is set to True in settings.py, HttpRequest.build_absolute_uri uses the X-Forwarded-Host header instead of request.META['HTTP_HOST'] or request.META['SERVER_NAME'].
I will not delve too much into the proxy setup part (as it is more related to professional network administration than to programming in the scope of this site) but for nginx it should be something like:
location / {
...
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
...
proxy_pass http://upstream:port;
}
Probably the best solution as it is fully dynamic, you don't have to change anything if the public scheme/hostname changes in the future.
If the internal and external scheme differ as well you may want to set SECURE_PROXY_SSL_HEADER in settings.py to something like this:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
And then add the following to the server config:
proxy_set_header X-Forwarded-Proto https;
2) Use the same hostname for public and private servers
Lets say your public hostname is "host.example.com": you can add a line like this to your /etc/hosts (on Windows %windir%\System32\drivers\etc\hosts):
127.0.0.1 host.example.com
Now you can use the hostname in the nginx config:
proxy_pass http://host.example.com:port;
When the internal and external scheme differ as well (external https, internal http), you may want to set SECURE_PROXY_SSL_HEADER as described in the first solution.
Every time the public hostname changes you will have to update the config but I guess this is OK for small projects.
I got mine working using proxy_redirect
Lets say you have a container or an upstream with the name app and you want it to return 127.0.0.1 as the host, Then your config should include:
server {
listen 80;
location / {
proxy_pass http://app:8000;
proxy_redirect http://app:8000 http://127.0.0.1:8000;
}
}
Here's my final config:
server {
listen 80;
location / {
proxy_pass http://app:8000;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect http://app:8000 http://127.0.0.1:8000;
}
}
Also checkout this article for a detailed explanation https://mattsegal.dev/nginx-django-reverse-proxy-config.html
I had a problem same as the question, I used nginx, gunicorn and django on production without docker.
get_current_site(request).domain
returned localhost so I have some issue in drf yasg base url. Simply I solved it by adding
include proxy_params;
to nginx conf.

nginx reverse proxy to apache mod_wsgi django app

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.

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.