Checking proxy set header forwaded by nginx reverse proxy (Django app) - python

I'm using nginx as reverse proxy with gunicorn for my Django app, and am new to webserver configuration. My app has a postgres backend, and the machine hosting it has Ubuntu 14.04 lts installed.
I have reason to suspect that my nginx configuration is not forwarding proxy set header to the Django app correctly. Is there a way I can see (e.g. print?) the host, http_user_agent, remote_addr etc. forwarded, on the linux command line to test my gut feel?
Secondly, how do I check whether my Django app received the correct forwarded IP? E.g. can I somehow print?
/etc/nginx/sites-available/myproject:
server {
listen 80;
server_name example.cloudapp.net;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/mhb11/folder/myproject;
}
location / {
proxy_set_header Host $host;
proxy_set_header User-Agent $http_user_agent;
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://unix:/home/mhb11/folder/myproject/myproject.sock;
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/mhb11/folder/myproject/templates/;
}
}

All you have to do is print out request.META at the Django project level to see what all of those values are being set to. This automatically happens for you if you get an error and debug is set to True (just scroll down, you'll see a big table with all request.META values populated therein).
Or you can print it yourself from your views.py, or if that doesn't work, then from any middleware you have. You can even write custom middleware for this. Let me know if you need further clarification on this, I can give you basic code snippets too.

This question was posted a long time ago but since I landed here when needed help, below are some code which I ended up using to attain the same goal for the help of other people.
def getClientIP(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[-1].strip()
else:
ip = request.META.get('REMOTE_ADDR')
return ip

Related

Django and nginx do not accept PATCH requests, resulting in a 400 bad request error

I work on a Django project + django-rest-framework. On localhost, PATCH requests work perfectly fine. However, on server, PATCH requests do not work. I get a 400 Bad request error. I use nginx to configure the web server.
Here is my configuration:
server {
listen 80;
server_name x.y.z.com;
root /var/www/path-to/project;
location / {
error_page 404 = 404;
proxy_pass http://127.0.0.1:5555/;
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_intercept_errors on;
}
}
I get this error when I try PATCH requests on server :
How can I make so that django accept PATCH requests? The log does not show anything. As if it does not even receives the request. I run the django server like this:
python manage.py runserver 5555
Friend, I faced this problem, I made all the possible settings in nginx, but the problem was in my js fetch that tried with the patch method in lowercase, 'patch', changing to 'PATCH' worked normally.

How to set up nginx to take up cloudfront url instead of the proxy pass for the backend server?

I have set up AWS Cloudfront Distribution for streaming objects from one of my S3 bucket. After generating urls, I am able to stream. Now since I have a server running in EC2 and my web app is backed by Nginx with already configured proxy_pass for the backend server. Now how do I use that generated cloudfront url for files to start playing them in my web app.
I am totally new to nginx following things I have tried
here is my nginx server config
server {
listen 8888;
server_name localhost;
}
location /app{
alias /opt/mw_web_app;
index index.html index.htm;
}
#Create proxy_pass for DataService.
location /service/{
proxy_pass http://server-ip:9003/;
proxy_set_header USER-IP $proxy_add_x_forwarded_for;
}
First fix your confguration and move the second curly brace to the end . then allow your server to be default server to assign all requests to this server
server {
listen 8888;
server_name localhost default_server;
location /app{
alias /opt/mw_web_app;
index index.html index.htm;
}
#Create proxy_pass for DataService.
location /service/{
proxy_pass http://server-ip:9003/;
proxy_set_header USER-IP $proxy_add_x_forwarded_for;
}
}
second, you sould use cloud front url direclty or assign CNAME using your own domain. if you use CF through your nginx CF will be useless with extra fees.
After a try and going to through Nginx Docs : Following worked for me and I a able to stream using cloudfront :
server {
listen 8888;
server_name localhost;
}
location /app{
alias /opt/mw_web_app;
index index.html index.htm;
}
#Create proxy_pass for DataService.
location /service/{
proxy_pass http://server-ip:9003/;
proxy_set_header USER-IP $proxy_add_x_forwarded_for;
}
#Create proxy_pass for DataService.
location /cloudfront/{
proxy_pass https://ddddddddd.cloudfront.net/;
}
}
PS: thanks #Ahmed Abdelazim for your time and yeah there was a syntax error also which u pointed out

Static & Media files 404 behind NGINX proxy pass

I have what I believe to be a slightly convoluted Django/Gunicorn/NGINX stack that is giving me trouble as I try to migrate it from the django development server to a production setup with Gunicorn and NGINX. Specifically, I'm having trouble serving static files.
SYSTEM ARCHITECTURE: I have one physical server with a public IP address. This physical server hosts 3 VM's on a private virtual network (NAT). Each VM run's it's own django project on port 8001. I forward port 8001 on each VM to unique available ports on the physical machine. So, in summary, the architecture looks like the following:
PRIVATE VIRTUAL NETWORK VM's:
VM1 runs "site 1" on VM1 port 8001
VM2 runs "site 2" on VM2 port 8001
VM3 runs "site 3" on VM3 port 8001
HOST SERVER:
Publishes "site 1" on host port 8001 (VM port 8001 fwd.to Host port 8001)
Publishes "site 2" on host port 8002 (VM port 8001 fwd.to Host port 8002)
Publishes "site 3" on host port 8003 (VM port 8001 fwd.to Host port 8003)
This works really well for development with the django development server. I just need to include a port # in the URL. As in:
myserver.edu:8001 for site 1
myserver.edu:8002 for site 2
myserver.edu:8003 for site 3
For production I would like to setup NGINX to serve the sites as:
myserver.edu/site1 for site 1
myserver.edu/site2 for site 2
myserver.edu/site3 for site 3
I installed NGINX on the host machine and configured it to use TLS. The NGINX configuration on the host machine defines 3 locations below with following config. You can see that I use the proxy_pass to route traffic for each site to the Virtual Network on the host machine.
location /site1/ {
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://192.168.122.243:8001/;
}
location /site2/ {
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://192.168.122.244:8001/;
}
location /site3/ {
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://192.168.122.245:8001/;
}
So any request for:
List item
myserver.edu/site1 goes to port 8001 on VM1
List item
myserver.edu/site2 goes to port 8001 on VM2
List item
myserver.edu/site3 goes to port 8001 on VM3
On VM1 I have a django site + gunicorn + NGINX with the following config (same setup on all VMs):
server {
listen 8001;
server_name 0.0.0.0;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/rcrv/bubbles/s2uds_user/gui;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/rcrv/bubbles/s2uds_user/bubs.sock;
}
}
My Site 1 root URL from urls.py is this: url(r'^$', gv.home),
BEHAVIOR UNDER THE ABOVE NGINX PRODUCTION CONFIG:
If I browse site 1 on VM1 from within the NAT with a URL such as:
192.168.122.243:8001/
This will work perfectly - Static and media file are served
If I browse from public IP space with a URL such as:
myerver.edu/site1/
This will render all dynamic content from django but will fail to serve static content (with a 404). My browser developer console shows that the browser is looking for the static content at https://myserver.com/static
Note that I expected it to look for static content at myserver/site1/static
If I modify that URL directly in the browser to be myserver.com/site1/static I can access the static content that was missing
ATTEMPTS TO MITIGATE/FIX INCLUDE:
I changed the location block on the NGINX config of the VM to be:
location = /site1/static/
No luck.
Debugging shows that the browser is still trying to find the static content at: myserver.edu/static
QUESTION:
How the heck do I modify or fix the configuration such that django includes that "/site1/" part in the static URL? I'm inclined to think that this problem is not an NGINX config issue but instead a django problem. Rather, I believe I need to tell django to prepend /site1/ to it's static URL.
Ideas? I've read numerous responses to similar django static file issues but yet on that fixes this.
Thank you.
UPDATE: I've started to figure this out. Here is what worked for me.
I created a /static/ directory at /var/www/static on each VM and set the STATIC_ROOT in the settings.py file to be this location, then ran collect static to copy all static content to this directory.
I then modified static file location block within the NGINX conf on the VM to be:
location /static/ {
root /var/www/;
}
Finally I modified the STATIC_URL in settings.py from: STATIC_URL = /static/ to STATIC_URL = /site1/static/
The result is the static content is now served in production under NGINX. The cause was my incomplete understanding of static content methods in general. Typing out the question here sort of clarified the problem and led me to the solution. Hopes this helps someone with a similar architecture. Now to fix the media files - likely the same approach.

Removing the port number from URL

I'm new to anything related to servers and am trying to deploy a django application. Today I bought a domain name for the app and am having trouble configuring it so that the base URL does not need the port number at the end of it. I have to type www.trackthecharts.com:8001 to see the website when I only want to use www.trackethecharts.com. I think the problem is somewhere in my nginx, gunicorn or supervisor configuration.
gunicorn_config.py
command = '/opt/myenv/bin/gunicorn'
pythonpath = '/opt/myenv/top-chart-app/'
bind = '162.243.76.202:8001'
workers = 3
root#django-app:~#
nginx config
server {
server_name 162.243.76.202;
access_log off;
location /static/ {
alias /opt/myenv/static/;
}
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';
}
}
supervisor config
[program:top_chart_gunicorn]
command=/opt/myenv/bin/gunicorn -c /opt/myenv/gunicorn_config.py djangoTopChartApp.wsgi
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor_gunicorn.err.log
stdout_logfile=/var/log/supervisor_gunicorn.out.log
Thanks for taking a look.
You should bind to port 80, the default http port. Then make sure in /etc/nginx/sites-enabled/, your are listening on port 80.
By binding to port 80, you will not need to explicitly specify one in your url.

Redirect http to https with nginx instead of using django-sslify?

I tried to use django-sslify and django-secure to redirect all http requests to https, but i just can't get it to work. Is it a valid solution to redirect them with nginx instead, like it is shown here: link
Or, maybe someone could explain, what is wrong with my config right now:
Before i added "proxy_set_header Host $host;" to the second server block it redirected nicely, but forms wouldn't work, because the csrf protection threw referrer errors.
server {
listen 80;
server_name domain.com;
location /static {
alias /home/adrian/sites/www.domain.com/static;
}
location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/www.domain.com.socket;
}
}
server {
listen 200.200.200.200:443;
server_name domain.com;
location /static {
alias /home/adrian/sites/www.domain.com/static;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://unix:/tmp/www.domain.com.de.socket;
}
ssl on;
ssl_certificate /etc/nginx/ssl/ssl.crt;
ssl_certificate_key /etc/nginx/ssl/domain.com.de.key;
ssl_prefer_server_ciphers on;
}
Okay, never mind. Django-sslify just didn't work for some reason and so i retried django-secure with
proxy_set_header Host $host;
set and it did work like a charm. But i would really like to hear, if it would be better or more efficient to redirect with nginx and i will accept that answer. Thanks.

Categories

Resources