nginx location and Django auth - django

I'm trying to create a NGINX redirect based on an URL param in the querystring. Basically having:
http://localhost/redirect/?url=https://www.google.it/search?dcr=0&source=hp&q=django&oq=django
and
location /redirect/ {
proxy_cache STATIC;
# cache status code 200 responses for 10 minutes
proxy_cache_valid 200 1d;
proxy_cache_revalidate on;
proxy_cache_min_uses 3;
# use the cache if there's a error on app server or it's updating from another request
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# don't let two requests try to populate the cache at the same time
proxy_cache_lock on;
# Strip out query param "timestamp"
if ($args ~ (.*)&timestamp=[^&]*(.*)) {
set $args $1$2;
}
return 302 $arg_url$args;
}
Now, only Django authenticated users (JWT/Cookie) can use the /redirect?url= end point, hence is it possible to implement a session/cookie check without opening a proxy to the entire world?
Anyway I could do it at the Django level (https://github.com/mjumbewu/django-proxy/blob/master/proxy/views.py) but I suppose it's faster and less computationally expensive at the NGINX level.
Thanks,
D

redirecting & proxying is different things, for getting django-proxy functionality you need to use nginx reverse proxy option instead of redirect.
# django-proxy code fragment
response = requests.request(request.method, url, **requests_args)
proxy_response = HttpResponse(
response.content,
status=response.status_code)
Nginx config for reverse proxying & auth
server {
listen 80;
server_name youtdomain.com;
location / {
# use django for authenticating request
auth_request /django-app/;
# a proxy to otherdomain
proxy_pass http://otherdomain.com;
proxy_set_header Host otherdomain.com;
}
location /django-app/{
internal; # protect from public access
proxy_pass http://django-app;
}
}
Django app should return 200 status code for authenticated users 401 otherwise, you can read more details about auth_request here

Based on the previous answers (thanks!) this is the solution:
http {
upstream app_api {
# server 172.69.0.10:8000;
server api:8000;
# 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).
# server unix:/var/www/gmb/run/gunicorn.sock fail_timeout=0;
}
server {
location = /auth {
proxy_pass http://app_api/api-auth/login/;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
location /redirect/ {
auth_request /auth;
proxy_cache STATIC;
# cache status code 200 responses for 10 minutes
proxy_cache_valid 200 1d;
proxy_cache_revalidate on;
proxy_cache_min_uses 3;
# use the cache if there's a error on app server or it's updating from another request
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# don't let two requests try to populate the cache at the same time
proxy_cache_lock on;
# Strip out query param "timestamp"
if ($args ~ (.*)&timestamp=[^&]*(.*)) {
set $args $1$2;
}
return 302 $arg_url$args;
}

Related

site cannot reached after nginx restart - AWS EC2

I am following the tutorial and completed it without any error, when I start nginx it showed me welcome page but after I restart nginx chrome is showing
This site can’t be reached.
I am accessing it by my public IP.
Here is my security group of instance (Inbound)
(Outbound)
Here is my nginx conf file:
upstream sample_project_server {
# 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).
server unix:/home/ubuntu/django_env/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name <my public ip>;
client_max_body_size 4G;
access_log /home/ubuntu/logs/nginx-access.log;
error_log /home/ubuntu/logs/nginx-error.log;
location /static/ {
alias /home/ubuntu/static/;
}
location /media/ {
alias /home/ubuntu/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://sample_project_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/ubuntu/static/;
}
}
any suggestions ? I am really frustrated, because every thing done perfectly but after restarting nginx, site is not reachable.

Nginx always falls back to default config

My stack is django, gunicorn, nginx and supervisor running on a VPS from DigitalOcean.
Supervisor is running the program correctly but I always get the NGINX welcome page. If I delete the default nginx config file everything works and I get the website.
Here are my custom settings:
upstream maet_app_server {
# 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).
server unix:/webapps/maet/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name maet.bg www.maet.com;
client_max_body_size 4G;
access_log /webapps/maet/logs/nginx-access.log;
error_log /webapps/maet/logs/nginx-error.log;
location /static/ {
alias /webapps/maet/website/static/;
}
location /media/ {
alias /webapps/maet/website/static/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://maet_app_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/maet/website/static/;
}
}
How do I change it to use this config instead of the default one?
I don't want to delete the default file because I need it for let's encrypt ssl.

How to deploy django on VPS with external subdomain.?

Good day.
I have a web app that I have developed using django. I tested fine on my local, and I'm happy with how it works.
However I'm facing an issue bringing it online I used those two guides to reach my deployment:
https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04
and
http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/
However my page is giving me a forbidden page.
I suspect my issue is with the way I'm handling the subdomain. So the site . has been developed using php, and I have worked on my part with django and been provided with a subdomain which is member.domain.com, So I'm deploying it on the VPS and have to make it use the subdomain.
This is how my allowed hosts looks in the settings.py
ALLOWED_HOSTS = ['member.domain.com']
and
in my nginx:
upstream app_server {
# 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).
server unix:/home/path/project/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name member.domain.com;
client_max_body_size 4G;
access_log /home/path/project/logs/nginx-access.log;
error_log /home/path/project/logs/nginx-error.log;
location /static/ {
alias /home/path/project/src/static/;
}
location /media/ {
alias /home/path/project/src/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://app_server;
break;
}
}
# Error pages
error_page 502 503 504 /500.html;
location = /500.html {
root /home/path/project/src/static/;
}
}
I'm not sure what I am doing wrong.
I will appreciate any help
To respond to 'example.com' and any subdomains, start the domain with a dot
ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
I didn't even try how to run django on subdomains, but from article link you shared, you missed some configuration in your settings.py
ALLOWED_HOSTS = ['member.domain.com']
Changed
ALLOWED_HOSTS = ['.domain.com']
Hope this will solve your problem

Django, Nginx, HTTPs and HttpResponseRedirect

I'm receiving a 404 error from Nginx when attempting to return an HttpResponseRedirect from Django. This is all happening under HTTPs The flow goes something like this:
User goes to a page
Enters some information in a form
The view process the form after POST and then attempts to redirect the user to a different page.
Except, instead of redirecting to the page, Nginx just eventually servers its 404 page.
I can get this to work in development while not under Nginx and HTTPs, so I suspect this has something to do with my Nginx setup. I have this working successfully on other servers so I'm unsure why I cannot get it working here
Sample Django view:
#login_required()
def index(request):
if request.method == 'POST':
form = ShortenerForm(request.POST)
if form.is_valid():
# Do stuff
return HttpResponseRedirect(reverse('shortener_thankyou'))
else:
form = ShortenerForm()
return render(request, 'shortener/index.html', {'form': form})
Nginx
upstream apollo2_app_server {
# 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).
server unix:/webapps/apollo2/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name apollo.mydomain.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/ssl/bundle.crt;
ssl_certificate_key /etc/nginx/ssl/mydomain.com.key;
server_name apollo.mydomain.com;
client_max_body_size 4G;
keepalive_timeout 70;
access_log /webapps/apollo2/logs/nginx-access.log;
error_log /webapps/apollo2/logs/nginx-error.log;
location /static/ {
alias /webapps/apollo2/static/;
}
location /media/ {
alias /webapps/apollo2/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://apollo2_app_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/apollo2/static/;
}
}
Nginx error
2015/04/24 11:04:10 [error] 18139#0: *3395 upstream prematurely closed connection while reading response header from upstream, client: 192.168.0.119, server: apollo.mydomain.com, request: "POST /shortener/ HTTP/1.1", upstream: "http://unix:/webapps/apollo2/run/gunicorn.sock:/shortener/",
I've tried a number of different solutions involving proxy_set_header X-Forwarded-Protocol $scheme; in Nginx and Djangos SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') but without luck.
It turned out that this had nothing to do with Nginx, SSL or Django. IT changed one of our DNS servers without notifying me. The response was timing out because it could not resolve DNS. Updating to the new DNS server in /etc/resolv.conf solved the issue.

Using Django, switched from heroku + gunicorn to digitalocean + nginx + gunicorn, site now broken

I had my django app on heroku for a while with no problems. I now want to move it to a digital ocean droplet, partly as a learning exercise, partly for scalability (and cost) reasons.
After following this excellent tutorial almost to the letter, the app is working but with a huge gotcha: I now get an infinite redirect loop when I try to log in to the admin site. The first request is a POST ?next=/admin/ with the username and password, this gets a 302 response to redirect to GET /admin/, which gets a 302 response redirect to ?next=/admin/, and so on.
I have spent 2 or 3 hours with google and various nginx tutorials and this is the first time my "google the error message, copy and paste random code snippets, repeat" algorithm has ever failed me, I'm hoping the reason is that the error is trivial to solve and I just can't see it?
If it's not trivial to solve, let me know and I'll post more info.
Thanks in advance
edit 1: my nginx config file for the app is basically a verbatim copy of the tutorial. It looks like this:
upstream hello_app_server {
# 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).
server unix:/webapps/hello_django/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name example.com;
client_max_body_size 4G;
access_log /webapps/hello_django/logs/nginx-access.log;
error_log /webapps/hello_django/logs/nginx-error.log;
location /static/ {
alias /webapps/hello_django/static/;
}
location /media/ {
alias /webapps/hello_django/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://hello_app_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/hello_django/static/;
}
}