How to delpoy drf static files and react app nginx config - reactjs

I have a simple nginx config. But when I uncomment Django static path for admin react starts return 404 and can't find its main.js files. React serves with serve -s build from their docs. Please, help.
server {
listen 80;
server_name server_ip;
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://localhost:3000;
}
#location /static/ {
# root /var/www/html;
#}
location ~* ^/(api|path/admin) {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}

Instead of just having var/www/html which is really anything in the root directory because I think that can create conflicts. because nginx is trying to find the build folder inside of the static folder which is not true.
I think if you copied the build folder in the /static I think it would work.
I have not really gone through this kind of issue before but I hope it helps.

Related

How to set up nginx config for a React.js app deployed on AWS ECS with path-based routing load balancer

I have an application which consists of two containers:
a backend node.js server on express.js, referred to as 'app-server'
a front-end react.js client based on create-react-app, referred to as 'app-client'. This one uses an nginx server to set up reverse proxy for /api requests to the application - like this post describes
Both are dockerized and deployed on AWS ECS Fargate and are supposed to be hosted on the same domain example.com, just different paths, respectively /app-server and app-client. So the users would access the app via https://example.com/app-client. In the future we would like to host more apps on the same domain using path based routing.
To achieve that we have defined a rule on the Application Load Balancer listener on EC2 which looks like this:
IF
- Path is: /app-client*
- Host is: example.com
THEN
- Forward to
- app-client-service-alb-h: 1 (100%)
- Group-level stickiness: Off
Also tested - Path is: /app-client, without the * at the end.
I managed to adjust the backend express server to work with this scenario but I'm struggling to make the React.js app work with the path forwarding - it just shows a blank page (worked without a problem when it was hosted directly on a domain, let's say http://app-client.com).
My guess is it has something to do with the nginx config because the request URL's are correct but there are just no .html, .js and .css files there.
Dockerfile looks like this:
FROM node:11.5.0 as builder
WORKDIR /usr/src/app
ADD ./ /usr/src/app
RUN npm install && \
npm run build
# ------------------------------------------------------
# Production Build
# ------------------------------------------------------
FROM nginx:1.16.0-alpine
COPY --from=builder /usr/src/app/build/ /usr/share/nginx/html
RUN rm -rf /etc/nginx/conf.d
COPY conf /etc/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Nginx config is set up this way:
server {
listen 80;
server_name example.com;
location /api {
proxy_pass https://example.com/app-server;
proxy_pass_request_headers on;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
React app's package.json file was adjusted by adding homepage setting:
"homepage": "/app-client"
Also tried with "homepage": "https://example.com/app-client". In both scenarios requested paths look correct, for example:
https://example.com/app-client/static/js/main.32859df6.chunk.js
The problem is that there is nothing found under this address, the page is blank. That's why I am assuming that nginx config needs to be adjusted to provide the file from correct location but have no idea what to adjust (I did also test removing the "homepage" from package.json but that also didn't solve it.).
I tried changing the location to location /app-client { or location ^~ /app-client { but that didn't work:
location /app-client {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
I blindly followed many other solutions, for example:
Nginx Meets Amazon ECS: Hosting Multiple Back-End Services Using a Single Load Balancer
Based on this config
None of them fixed the problem and I'm a rookie in that area so I'm stuck... Please help :(
------- Edited -------
The issue is solved and I'm posting the answer in case someone else finds it helpful.
The Nginx config should look like this, with appropriate rewrite defined:
server {
listen 80;
# All files should be at this directory; put it above location, otherwise it was looking in a wrong directory somewhere in `/etc/...`
root /usr/share/nginx/html;
# Prefix app-client -> rewrite
location /app-client {
rewrite ^/app-client(?:/(.*))?$ /$1;
}
# proxy for backend server /api requests
location /api {
# the ending `/api` part depends on whether your server routes also start with `/api` or not, mine do hence it was required
proxy_pass https://example.com/app-server/api;
proxy_pass_request_headers on;
}
location / {
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
The issue is solved and I'm posting the answer in case someone else finds it helpful.
The Nginx config should look like this, with appropriate rewrite defined:
server {
listen 80;
# All files should be at this directory; put it above location, otherwise it was looking in a wrong directory somewhere in `/etc/...`
root /usr/share/nginx/html;
# Prefix app-client -> rewrite
location /app-client {
rewrite ^/app-client(?:/(.*))?$ /$1;
}
# proxy for backend server /api requests
location /api {
# the ending `/api` part depends on whether your server routes also start with `/api` or not, mine do hence it was required
proxy_pass https://example.com/app-server/api;
proxy_pass_request_headers on;
}
location / {
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
Here is an example of my microservices application hosted on AWS with ALB & ECS.
ECS has multiple backend services, react app static files being served from frontend container service which is NGINX reverse proxy.
NGINX_ALB is the ALB DNS name stored in env variable inside container during Dockerfile build.
Gets substituted into nginx config using:
CMD ["/bin/sh", "-c", "export NGINX_ALB && envsubst '$$NGINX_ALB' < /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/nginx.conf && nginx -g 'daemon off;'"]
upstream alb {
least_conn;
server ${NGINX_ALB}:80 max_fails=3;
}
server {
# ref https://www.veggiespam.com/bad-headers/
proxy_hide_header Server;
proxy_hide_header X-Powered-By;
proxy_hide_header X-AspNetMvc-Version;
proxy_hide_header X-AspNet-Version;
proxy_hide_header X-Drupal-Cache;
proxy_hide_header X-Drupal-Dynamic-Cache;
proxy_hide_header X-Generator;
proxy_hide_header X-Runtime;
proxy_hide_header X-Rack-Cache;
# proxy_set_headers moved to server directive allowing them to be referenced by all locations
proxy_http_version 1.1;
proxy_set_header Connection "";
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;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 300s;
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /auth/ {
proxy_pass http://alb;
proxy_redirect off;
}
location /api/sigma {
proxy_pass http://alb;
proxy_redirect off;
}
location /api/ {
proxy_pass http://alb;
proxy_redirect off;
}
location /db {
proxy_pass http://alb;
proxy_redirect off;
}
location /scheduler {
proxy_pass http://alb;
proxy_redirect off;
}
location /validator {
proxy_pass http://alb;
proxy_redirect off;
}
location /alarm/ {
proxy_pass http://alb;
proxy_redirect off;
}
location /reporter {
proxy_pass http://alb;
proxy_redirect off;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

Nginx Proxy Pass Issue - Docker, React and Express

I have a docker-compose set up that looks like this:
Containers:
Main nginx container gateway. The /todos/ route is proxy_passed to:
Another nginx container. This one proxy passes either to:
A React front end (for the todos app)
or
A node express api (which handles todo logic)
I'm trying to be able to call the todos api from the React app with process.env.PUBLIC_URL + "/api" in order to access the "/" route on my express api. However this isn't working, and I have to add another "/" to the React call to make it work - like this: process.env.PUBLIC_URL + /api/
Note: my React homepage is set to "/todos"
It's clearly a problem with how I'm doing the rewrites for the routes on Nginx, but I've tried every combination under the sun and can't get rid of the need for that trailing slash. Here are my Nginx configs:
The entry config:
upstream todosnginx {
server todosnginx;
}
server {
listen 80;
error_page 404 /404.html;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /todos {
rewrite /todos/(.*) /$1 break;
proxy_intercept_errors on;
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_pass http://todosnginx/;
}
}
And the todos nginx:
upstream todoclient {
server todoclient:3000;
}
upstream todoserver {
server todoserver:9000;
}
server {
listen 80;
location / {
proxy_pass http://todoclient/;
}
location /sockjs-node {
proxy_pass http://todoclient;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass http://todoserver/;
}
}
I've tried doing:
rewrite /api(.*) /$1 break;
in the todosnginx conf,
and
location /api/
and I've tried adding trailing slashes or deleting trailing slashes and many other combinations. It would be great if you knew where I was going wrong here.
Many thanks, R
rewrite /api(.*) $1 break;
if it doesn't work, post the logs.

Why can NGINX not load my react app with the right css & js files

So the issue i am facing is very frustating because is not clear to me what the problem is. I will do my best to describe it as best as i can.
I have a kubernetes cluster running in Azure. I have two components running which is a nginx ingress load balancer and a react application that is also running on a nginx server. Both services are running on their own pod. The load balancer is directing traffic to my react application via HTTPS.
Before this implementation i was exposing the react application directly to the internet. That was working good without any issue's since i am using the load balancer my react app does not work anymore.
This is the error that i am getting:
error1
error2
What the errors are saying is that the js and css files are loaded with the index.html code, so thats why my react app cannot be loaded. I tried to figure out why this is happening, but did not have any success. I also checked the files on the server and there they are not showing the content of the index.html files. They are showing the content that came out of my react build which is correct.
This is my config file for nginx:
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
The contents of my html folder:
Hope somebody can help me with this, thanks in advance and if you need more info pls let me know.
So the issue was with my nginx ingress.
This annotation was messing with the routing of my frontend application:
nginx.ingress.kubernetes.io/rewrite-target
My website is working!
Try adding try_files to your location block:
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html =404;
}
It will first look for the file in your root directory.
If it cannot find the file, it will serve your index.html file, which is what you want for a single page app.
Failing that, it will fall back to 404.
I hope this helps.
Static Block required to map static files
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name my_server_name;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
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-NginX-Proxy true;
proxy_bind 127.0.0.1;
proxy_pass http://localhost:3000/;
proxy_ssl_session_reuse off;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
location /static/ {
root /home/myusername/my-react-app-dir/build/;
}
}

React app doesnt launch from url location as set by nginx reverse proxy but does when port explicitly set

I'm trying to run a single react app on a separate port and using proxy pass from nginx to location '/app'
"http://localhost/app" -> React Application
The application is running under PM2 using its generated build with the command: 'pm2 serve build 3002'.
My thought was i do all this tested locally and then will port it to my own domain.
I've swapped 'localhost' for '127.0.0.1' just in case that had anything to do with it.
From online tutorials i've ended up with the following in my nginx "../sites-available/my_domain" file
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /var/www/my_domain/html;
index index.html index.htm index.nginx-debian.html;
try_files $uri $uri/ =404;
}
location /app {
proxy_pass http://localhost:3002;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
If i type "http://localhost:3002" into the url it works fine however "http://localhost/app" does not work and shows 404 error.
Side-note: "http://localhost" works fine and directs to the index.html stored at root.

Serve single file Angular app from S3 with nginx

I have an Angular app that consists of a single index.html file. The only others files are main.css and some image assets. I've already rediscovered there is no way to use S3 web hosting to serve it so I'm trying to set up nginx as a proxy. I have done this before but it was years ago and it wasn't with an Angular app and HTML5 push state. Here is the current nginx config server block I have.
server {
server_name foo.com;
set $s3_bucket 'foo.com.s3.amazonaws.com';
proxy_http_version 1.1;
proxy_set_header Host $s3_bucket;
proxy_set_header Authorization '';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header Set-Cookie;
proxy_ignore_headers "Set-Cookie";
proxy_buffering off;
proxy_intercept_errors on;
resolver 172.16.0.23 valid=300s;
resolver_timeout 10s;
location ~* ^/(assets|styles)/(.*) {
set $url_full '$1/$2';
proxy_pass http://$s3_bucket/live/$url_full;
}
location / {
rewrite ^ /live/index.html break;
proxy_pass http://$s3_bucket;
}
}
I don't assume anything with this config. It could all be completely wrong.
It does "work". I can go to foo.com and the site serves and I can navigate and it all work wonders. But it won't load any URL that is not /. All other redirect to / and that is a problem.
What am I doing wrong? All help appreciated.

Resources