How to serve React app AND Django blog from Nginx? - django

I'm using nginx to serve a React app from my domain root / and a Django blog app from /blog. I'm also using nginx to redirect all http to https.
The problem is some weird behaviour... If I navigate to the blog with a clear cache, it shows the blog. If I then navigate to the index page it shows the react app. All good so far. But then, if I return to /blog it continues to show the react app, not the blog! I think the problem involves caching, but I'm not sure where.
I am not using react-router, so I'm not sure how the urls could get redirected on the client side.
Here is my nginx config:
server {
listen 80;
server_name mydomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name mydomain.com;
root /production_build;
location /static/ {
root /var/www/mysite;
}
location /blog {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://upstream_django_server;
}
location /cms {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://upstream_django_server;
}
location / {
try_files $uri /index.html;
}
}

You should disable the service worker in react, as it is interfering with your /blog url and returning its own response the next time.
Since you are mixing 2 apps here, you don't want to take a risk of having something which is difficult to get rid of.
Service workers can be sometimes very nasty because of caching responses

Related

Serving Django and Vue with Nginx

I have a website which uses Django for the API and Vue for the frontend. Currently when I deploy the site I do the following:
Create a production build of the Vue app (npm run build)
Copy the Vue dist folder into a specific folder within the Django app
One of the Django urls is setup as a TemplateView which serves up the Vue index.html
By doing the above, Nginx in production simply serves up the Django app using gunicorn and everything works.
However I would prefer to have Nginx serve up the Vue index.html and static files. For example / will serve the Django app and /spa will serve the Vue app which will itself call the api.
Here is my current Nginx config:
upstream appserver_wsgi_app {
server localhost:8000 fail_timeout=0;
}
server {
listen 80;
server_name www.example.com;
rewrite ^(.*) https://$server_name$1 permanent;
}
server {
server_name www.example.com;
listen 443 ssl;
...
...
...
location /static {
autoindex on;
alias /home/user/static_django_files/;
}
location /media {
autoindex on;
alias /home/user/media_django_files/;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request-filename) {
proxy_pass http://appserver_wsgi_app;
break;
}
}
}
What needs to be changed in Nginx so that it will serve the Vue index.html and static files as well as the Django app? Also, does anything need to change on the Vue side since im currently just calling the api as follows:
axios.post("/api/dosomething/", data)
EDIT
I have added the following to my nginx config and uploaded the Vue dist folder:
location /spa {
autoindex on;
alias /path/to/dist/;
try_files $uri $uri/ /index.html;
}
I have also added the following to vue.config.js:
baseUrl: '/spa'
And to my Vue Router: mode: history
When restarting nginx, the index.html page for the vue app attempts to load in the browser but it cannot find the css and js files which it tries to find at:
www.example.com/spa/js/...
www.example.com/spa/css/...
I have a similar setup where I run the Django REST backend with uwsgi on port 8090 and serve the production build of angular 4 frontend via nginx. Here is my nginx.conf
server {
listen 80;
server_name **url**;
rewrite ^ https:// **url** $request_uri? permanent;
}
server {
listen 443 ssl;
server_name **url**;
ssl_certificate **.pem;
ssl_certificate_key **.key;
root *path to your vue production build folder where index.html resides*;
index index.html;
error_page 502 /gateway.html;
location /assests {
autoindex on;
alias *path to you Django assets *;
}
location /static {
autoindex on;
alias *path to you static files both django static files and vue related static files*;
}
// this to server the django admin
location /manage/ {
proxy_pass http://127.0.0.1:8090/manage/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
// this is for the REST backend
location /api/{
proxy_pass http://127.0.0.1:8090;
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;
}
}
I think similar setup should work for Django + Vue.js project. Let me know if it works.
** EDIT
for your second issue create another location with '/spa/static' in nginx.conf similar to the '/static'.

How to config nginx proxy pass using subfolder domain whith gunicorn Django

How can I configure ngnix to redirect a proxypass from a domain with subfolder to /?
Example:
https://example.com/yoursub/
to
localhost without /yoursub/ prefix
At the moment the direct access to the server ip http://xxx.xxx.xxx.xx/ from the intranet works without problems.
my nginx config file:
upstream app_server {
server unix:/home/myname/APP-Server/gunicorn/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
# add here the ip address of your server
# or a domain pointing to that ip (like example.com or www.example.com)
server_name 123.456.789.1;
keepalive_timeout 5;
client_max_body_size 4G;
access_log /home/myname/APP-Server/logs/nginx-access.log;
error_log /home/myname/APP-Server/logs/nginx-error.log;
location /static/ {
alias /home/myname/APP-Server/static-root/;
}
# checks for static file, if not found proxy to app
location / {
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
If it's relevant: The backend is a django app with a gunicorn server. Do I have to consider anything about the redirect from https to http? I have no control over the base domain.
If I understand correctly, you want to remove the first part of the URI. There are multiple ways you can do that, but the easiest is probably with the alias directive, which will remove the portion of the URI that matches the current location block:
location /foo/ {
alias /home/myname/APP-Server/static-root/; # It doesn't really matter what you put here, since you're proxying everything.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
If your Nginx server is running on foobar.example and you request http://foobar.example/foo/bar, the upstream server will see a request for http://foobar.example/bar.
The alias directive can be a bit buggy/unintuitive, so it's best to keep your location directive top-level (not nested within other location blocks) and as simple as possible.
If instead you want to add a prefix to the URI, you can do that within the proxy_pass directive itself:
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server/foo$uri$is_args$args;
}
If your Nginx server is running on foobar.example and you request http://foobar.example/bar, the upstream server will see a request for http://foobar.example/foo/bar
Try this:
server {
...
location #proxy_to_app {
...
proxy_pass http://app_server/; # note the trailing slash
}
}
Explanation
As per the nginx docs:
If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive.
Since / location matches anything, then everything will be replaced by / (the trailing slash in proxy_pass) before being proxied to the upstream.
The way I handle this is with a rewrite rule:
location /yoursub {
rewrite /yoursub(.*) $1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
The rewrite will convert your url from /yoursub/path/to/view to /path/to/view for your app server.

nginx configuration location regular expression

I'm using an nginx server to proxy a request to another location, but I'm having trouble getting the regex to work. I think part of my issue is that I don't completely understand how the proxy works as I copy/pasted it from somewhere else I saw online.
Here is my nginx-config file:
server {
listen 8080;
location /api/data {
proxy_pass http://jsonserverlocation:3000;
proxy_set_header Host mywebsitewithjson.com;
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 https;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}
When I make requests like .../api/data/types the server redirects to the resource as expected. However, when I make requests like .../api/data/types/C I get a 404. How do I get the nginx to pass any request that begins with /api/data/ to redirect with my proxy, regardless of how many slashes there are after data?

Configure Django App as nginx location

I am trying to deploy a Django app along a static html website. The general www.example.com will provide the basic website. The URI /app should then proxy to a Gunicorn WSGI server. The nginx configuration in sites-enabled looks as follows:
upstream gunicorn {
server 127.0.0.1:8000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/website;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location /app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://gunicorn;
}
}
I am getting a 404 error when trying www.example.com/app. It seems the URI gets messed up somehow. The complete URL that is created is http://www.example.com/accounts/login/?next=/app/
Setting up the App alone exactly following this tutorial http://hackedexistence.com/project/raspi/django-on-raspberry-pi.html does work.
Is the setup I am aiming at even possible? And if yes, where is my misunderstanding of the location concept?
You need to set the SCRIPT_NAME header in your location directive.
proxy_set_header SCRIPT_NAME /app;
See this blog post for an example.

How to configure nginx for a rails single page application?

I am trying to configure nginx to render a Rails 4 single page application. The index page exists within a Rails template index.html.erb. Javascript and CSS are both on a CDN. The current configuration allows the page to load, and I can navigate the entire site. The issue comes when I try to reload the page or attempt to navigate to a page via the address bar: mysite.com/about. What am I missing? I have experience with single page apps but usually the page is external to Rails.
I am using:
Rails 4
Unicorn v4.3.1
Openresty 1.5.11.1
Nginx configuration:
upstream rails_server {
server unix:/var/www/mysite.org/api/shared/tmp/.unicorn.mysite-org.sock fail_timeout=0;
}
server {
listen 80 default_server deferred; # for Linux
server_name staging.mysite.org;
client_max_body_size 5m;
keepalive_timeout 5;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
# proxy_cookie_domain api.local.mysite.org local.mysite.org;
proxy_pass http://rails_server;
}
location ~* /application.*\.css$ {
return 301 $scheme://css.mysite.org$request_uri;
}
location ~* /application.*\.js$ {
return 301 $scheme://js.mysite.org$request_uri;
}
}