Problems with nginx try_files setup - django

I'm trying to set up a project using django, gunicorn and nginx and I'm having trouble with the nginx configuration. More precisely when I use try_files.
If I use if (!-f $request_filename) {...} everything works fine but if use
try_files ... Django generates the exception:
Invalid HTTP_HOST header: 'myproject_server'. The domain name provided is not valid according to RFC 1034/1035.
Once everything works using the if ... I assume that the other settings
(gunicorn etc) are correct.
The configuration files I'm using are:
/home/myproject/myproject/settings.py (django)
...
ALLOWED_HOSTS = [192.168.200.100, ]
...
/etc/nginx/sites-available/myproject (this one WORKS)
upstream myproject_server {
unix server:/home/myproject/run/gunicorn.sock fail_timeout = 0;
}
server {
listen 80;
server_name 192.168.200.100;
root /home/myproject;
location /media/ {}
location /static/ {}
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;
if (!-f $request_filename) {
proxy_pass http://myproject_server;
break;
}
}
}
/etc/nginx/sites-available/myproject (this one DOES NOT WORK)
upstream myproject_server {
unix server: /home/myproject/run/gunicorn.sock fail_timeout = 0;
}
server {
listen 80;
server_name 192.168.200.100;
root /home/myproject;
location /media/ {}
location /static/ {}
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;
try_files $uri #myproject_backend;
}
location #myproject_backend {
proxy_pass $scheme://myproject_server;
}
}
What am I doing wrong?
Thanks in advance any help.
PS: English is not my native language so I apologize for the (many) errors.

proxy_set_header should be in the same location as proxy_pass.
location / {
try_files $uri #myproject_backend;
}
location #myproject_backend {
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://myproject_server;
}

Related

API connections from react(Axios) to Nginx (Docker/Django) doesn't work. ERR_CONNECTION_REFUSED

I have a problem with connecting my fronted(react/Axios) to backend(Django) data hosted on VPS using Nginx and docker. The problem is weird because I can connect to API by Postman. The issue appears when I try to get data from my frontend(localhost:3000) or from netlify app.
There is Nginx code:
upstream 127.0.0.1 {
server django_gunicorn:8000;
}
server {
listen 80;
location / {
proxy_pass http://127.0.0.1;
}
location /ws {
proxy_pass http://127.0.0.1;
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;
}
location /static/ {
alias /static/;
}
location /media/ {
alias /code/media/;
}
}
EDIT:
I changed my server name to django_api and i added three more lines in location /, afterwards everything works.
upstream django_api {
server django_gunicorn:8000;
}
server {
listen 80;
location / {
proxy_pass http://django_api;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /ws {
proxy_pass http://django_api;
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;
}

GET is working but POST is not working on Docker

The application is on Django configured with Docker. GET requests are working fine. But the POST requests are not working. I am adding the nginx.conf file below for the reference.
The POST request is necessary for authentication.
upstream app_server {
server djangoapp:8000 fail_timeout=0;
}
server {
listen 80;
server_name samplewebsite.com;
root /opt/djangoapp/src/samplewebsite/samplewebsite;
index index.html;
server_tokens off;
location / {
try_files $uri $uri/ /index.html;
}
location /media {
alias /opt/djangoapp/src/media/;
}
location /static {
alias /opt/djangoapp/src/static/;
}
location /api/ {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass http://app_server/;
}
location /admin/ {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass http://app_server/admin/;
}
client_max_body_size 128m;
}
The response of the POST request is Error code 405.
Let me know if I need to add more information to the question.

Modify nginx config to reverse proxy websockets properly

Current nginx config:
server {
listen 443 ssl http2;
server_name NAME www.NAME;
charset utf-8;
ssl on;
ssl_certificate /etc/nginx/ssl/NAME-cert.pem;
ssl_certificate_key /etc/nginx/ssl/NAME-key.pem;
location /static/ {
alias /home/ubuntu/NAME/static_collection/;
}
location /media/ {
alias /home/ubuntu/NAME/media_collection/;
}
location / {
proxy_pass http://localhost:8002;
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-Proto $scheme;
}
}
Everything works, apart from the websockets. I suppose this is because it doesn't deal with the http upgrade header... I've looked at the docs, but I can't figure out how to modify this config without breaking anything else.
Try this. Let me know if it works.
server {
listen 443 ssl http2;
server_name NAME www.NAME;
charset utf-8;
ssl on;
ssl_certificate /etc/nginx/ssl/NAME-cert.pem;
ssl_certificate_key /etc/nginx/ssl/NAME-key.pem;
location /static/ {
alias /home/ubuntu/NAME/static_collection/;
}
location /media/ {
alias /home/ubuntu/NAME/media_collection/;
}
location / {
proxy_pass http://localhost:8002;
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-Proto $scheme;
proxy_http_version 1.1;
proxy_read_timeout 86400;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}

How confiigure nginx with django-hosts?

I use django-hosts and nginx.
Example, hosts.py
host_patterns = patterns('project',
host(r'', 'urls', name=''),
host(r'beta', 'private_urls', name='beta'),
)
nginx.conf
server {
listen 80;
server_name example.ru *.example.ru 174.61.223.135;
access_log /var/log/nginx/example.log;
location /static/ {
alias /home/path/to/static/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
But when I turn on beta.example.ru, django does not take the settings from hosts.py. It takes on the url defaults host(r'', 'urls', name='') and not find urls from host(r'beta', 'private_urls', name='beta')
How do I configure nginx.conf?

Changing the Host passed to the backend

I have my frontend server running nginx. The backend is on another machine on the same VPN. This is its config:
server {
listen 80;
server_name *.vpn.domain.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://10.8.25.102:8100/;
proxy_redirect http://10.8.25.102:8100/ http://$server_name/;
}
}
I would like to pass a different host to the backend... I'd like the backend to receive, for requests done tosubdomain.vpn.domain.com the host subdomain.local.domain.com
Is there any way to do this? I'm looking for a regexp substitution (or even a substring substitution) but I'm having surprisingly little success... I thought it would be a piece of cake. I think the solution would be in the lines of
server {
listen 80;
server_name *.vpn.domain.com;
set $my_host $http_host;
replace $my_host .vpn. .local.
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $my_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://10.8.25.102:8100/;
proxy_redirect http://10.8.25.102:8100/ http://$server_name/;
}
}
It's just that I haven't found yet the proper syntax for replace $my_host .vpn. .local. I don't really care about multiple substitutions... I won't have a.vpn.a.vpn.domain.com
I finally figured it out, I can do
if ($http_host ~ ^(.*)\.vpn\.(.*)$) {
set $my_host $1.local.$2;
}
And then, as there're CSRF validations in place, I also need to rewrite the Referer... so this is how it ended up looking
server {
listen 80;
server_name *.vpn.domain.com;
set $my_host $http_host;
if ($http_host ~ ^(.*)\.vpn\.(.*)$) {
set $my_host $1.local.$2;
}
set $referer $http_referer;
set $referer_host no;
if ($http_referer ~ ^(https?://)([^/]+)(/.*)$) {
set $referer_host $2;
set $rewritten_referer $1$my_host$3;
}
if ($referer_host = $http_host) {
set $referer $rewritten_referer;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $my_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Referer $referer;
proxy_set_header IS_SECURE no;
proxy_pass http://10.8.25.102:8100/;
proxy_redirect https://$my_host/ https://$http_host/;
proxy_redirect http://$my_host/ http://$http_host/;
}
}