I'm trying to deploy a react app with nginx reverse proxy.
My server configuration block (/etc/nginx/sites-available/app2.conf) is as follow:
server {
listen 80;
listen[::]:80;
root/srv/app2/build;
index index.html index.html;
server_name _;
location / {
proxy_pass http://localhost:3001/;
try_files $uri $uri/ =404;
}
}
I'm using a docker to run the react app with port 3001 exposed.
I tried to use curl to see if it works. The curl command works as expected.
curl http://localhost:3001
However, when i tried to run in my web browser i got the following error:
Failed to load resource: the server responded with a status of 404 (Not Found) main.8ea061ea.chunk.css
Failed to load resource: the server responded with a status of 404
(Not Found) main.dcd07bc1.chunk.js
Failed to load resource: the server responded with a status of 404
(Not Found) 1.a6f3a221.chunk.js
Failed to load resource: the server responded with a status of 404
(Not Found) main.dcd07bc1.chunk.js
Failed to load resource: the server responded with a status of 404
(Not Found) main.8ea061ea.chunk.css
It seems that it failed to load all the static files (.css & .js) files.
Does anybody know how to resolve this?
Please check this https://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content/
You have to specify the way static files are to served depending upon the url requested for static files.
Hope it helps!
try using this config to build the docker
# build environment
FROM node:9.6.1 as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install react-scripts#1.1.1 -g --silent
COPY . /usr/src/app
RUN npm run build
# production environment
FROM nginx:1.13.9-alpine
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
never had any problem using this script. U might miss some nginx config or forgot to copy recursively, who knows if u didnt post the Dockerfile
*note: i didnt make it
credit: https://mherman.org/blog/dockerizing-a-react-app/
I think this is an elegant solution for nginx reverse proxy cofiguration.
/etc/nginx/sites-available/app2.conf
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:3001;
# recommended settings
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;
}
}
Don't forget symbolic link:
sudo ln -s /etc/nginx/sites-available/app2.conf /etc/nginx/sites-enabled/
Related
Build is working perfectly on my local PC with pm2, no errors at all. Every page loads perfectly, there are no 404 or 500 errors in fetching files. It's great! This is EXACTLY how I want it to run.
But when I try and deploy this on Ubuntu with pm2 I am getting two sets of errors:
I'll put screenshots here:
https://i.imgur.com/IdnEH7r.png
Written form:
Script_app-a44cfb7405f734c3.js
Script_buildManifest.js
Script_ssgManifest.js
Script_middlewareManifest.js
(And others) all are giving me a 500 Internal Server Error no matter what I do.
Attempted Solutions
I've tried many approaches and all of them end with this error/failure when I am navigating to my deployed website.
Upload manually with filezilla.
Git clone from my repository, build on the server (no build errors) and then deploy with pm2. No errors with pm2 either! But then I am given 404/500 errors.
I've tried this in different folders, I've tried it with a host of different commands. I am completely out of ideas and I've uploaded and tried to get my files on there and install packages and more.
Nginx error?
This might be nginx error? But the nginx settings work perfectly fine for a brand new "npx create-next-app#latest" Following this exact tutorial to the letter: https://www.youtube.com/watch?v=x6ci2iCckWc&t=658s&ab_channel=DigitalCEO
My nginx file
"server {
server_name specialservername.com;
gzip on;
gzip_proxied any;
gzip_types application/javascript application/x-javascript text/css text/javascript;
gzip_comp_level 5;
gzip_buffers 16 8k;
gzip_min_length 256;
location /_next/static/ {
alias /var/www/frontend/.next/static/;
expires 365d;
access_log off;
}
#EDITS
location ~ ^/_next/static/(.*)$ {
root /.next;
try_files "/static/$1" "/server/static/o$1" #proxy_pass;
}
#END EDITS
location / {
proxy_pass http://127.0.0.1:3000; #change to 3001 for second app, but make sure second nextjs app starts on new port in packages.json "start": "next start -p 3001",
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;
add_header Access-Control-Allow-Origin *;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/specialservername.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/specialservername.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host =specialservername.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name specialservername.com;
return 404; # managed by Certbot
}"
What I was Expecting
The NextJS build to be deployed on this server no different than it is on my local machine. On my local machine it's BEAUTIFUL!
If you're seeing an "Internal Server Error" when trying to access your Next.js application on Ubuntu with nginx, it's likely that there's an issue with your configuration.
Here are a few things you can try:
Check your nginx error logs: Look in your nginx error logs (typically located in /var/log/nginx/error.log) for any error messages that might indicate what's causing the issue.
Check your Next.js logs: You should also check your Next.js logs (usually located in the .next directory of your application) for any error messages that might indicate what's causing the issue.
Check your Next.js configuration: Make sure your Next.js configuration is set up correctly for production deployment. You should make sure that your next.config.js file has the necessary settings for production deployment, such as setting target: 'server', configuring your build options, and setting your asset prefix if necessary.
Check your environment variables: Make sure any environment variables that your application depends on are set correctly on your Ubuntu server.
Check for permission: Make sure file, build files on server has enough permissions.
Also if everything from above works fine than try dockerizing your application with nginx and run on local then simply mimic the same on server(ubuntu) that would definatly give you some clue.
and lastly, don't panic. š
When I run 'next start' on my Linux server, nextjs only seems to host on HTTP. I've installed let's encrypt but can't seem to find a way to link the certificate with the default next js server. However, I've seen that there is a solution that involves creating a server.js file to manually start up your next server but using that also inhibits nextjs's ability to use features such as server-side rendering and serverless functions. I find it hard to believe there isn't a way around this due to the mainstream use of nextjs?
If anyone has found a way around this or has any information, please share.
You need to set up nginx to route your domain to your Nextjs port. Check which port your nextjs is running. Example port 3000 is the default.
On your server, install nginx as normal. Many tutorials on the web. Once installed:
cd /etc/nginx/sites-available
nano example.com
Copy/Paste nginx setup from below
# *q is our domain, replace port 3000 with your port number
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:3000;
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;
}
# for letsencrypt
location ~ /.well-known {
allow all;
}
}
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
nginx -t
service nginx restart
Make sure your Nextjs is running.
Install Letsencrypt as normal. Many tutorials on the web.
sudo apt update && sudo apt install certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com
certbot certonly --standalone --preferred-challenges http -d example.com
certbot renew --dry-run
I'm trying to create a docker-compose using two services, a Spring Boot backend (running on port 8080) and React frontend running on Nginx.
The react app calls backend API like /api/tests.
However, when I run the docker compose and frontend makes a request, it always fails with 404 error: GET http://localhost/api/tests 404 (Not Found)
When I set the frontend dockerfile not to use Nginx, just npm start, it worked fine, but I would prefer using production build on Nginx.
Current frontend dockerfile:
FROM node:11.13 as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install
RUN npm install react-scripts#2.1.8 -g
COPY ./package-lock.json /usr/src/app/
COPY ./public /usr/src/app/public
COPY ./src /usr/src/app/src
COPY ./nginx.conf /etc/nginx/nginx.conf
RUN npm run build
FROM nginx:1.15.10-alpine
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
Nginx.conf:
server {
listen 80;
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control public;
expires 1d;
}
location /api {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://server:8080/;
}
}
docker-compose:
version: "3"
services:
server:
build: test-server/
expose:
- 8080
ports:
- 8080:8080
ui:
build: test-ui/
expose:
- 80
ports:
- 80:80
The react app has a line "proxy": "http://server:8080" in its package.json.
Nginx logs the following error:
2019/04/15 12:50:03 [error] 6#6: *1 open() "/usr/share/nginx/html/api/tests" failed (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET /api/tests HTTP/1.1", host: "localhost", referrer: "http://localhost/"
I found the problem. In the multi-stage build of the docker image, I accidentally copied the nginx.conf file into the builder image, not the production one.
The fixed Dockerfile now looks like this:
# build environment
FROM node:11.13 as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install
RUN npm install react-scripts#2.1.8 -g
COPY ./package-lock.json /usr/src/app/
COPY ./public /usr/src/app/public
COPY ./src /usr/src/app/src
RUN npm run build
# production environment
FROM nginx:1.15.10-alpine
COPY --from=builder /usr/src/app/build /var/www
COPY ./nginx.conf /etc/nginx/nginx.conf
CMD ["nginx", "-g", "daemon off;"]
and nginx.conf:
server {
listen 80;
include /etc/nginx/mime.types;
root /var/www;
index index.html index.htm;
location /api {
resolver 127.0.0.11;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://server:8080$request_uri;
}
location / {
try_files $uri $uri/ =404;
}
}
It works fine in dev because you have a webpack dev server proxying you requests to port 8080 ( the "proxy": "http://server:8080" line ), but this is gone in production builds.
Adding $request_url to you proxy_pass should fix it.
location /api {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://server:8080$request_uri;
}
It will fail since you are accessing to api http://localhost/api/tests, while in your docker-compose file you point api to port 8080.
So try this one:
http://localhost:8080/api/tests
I would suggest you to use ENVIRONMENT VARIABLES so you can change it whenever you change your port or something. Then in React you can access them by:
ex. You can set them from your terminal
SET REACT_APP_API_URL=http://localhost:8080
and access it by
process.env.REACT_APP_API_URL
Or you can even set it in your Dockerfile or docker-compose file.
Him
Iāve got a problem that I canāt solve.
When I query my springboot backend it works fine. The password is asked then when Iām authenticated, I receive the answer.
But, if I first call the front-end, (the basic authentication also works) but the nginx proxy doesnāt forward queries to the spring-boot backend anymore.
Could you please help me to figure out whatās wrong with my config. Do I have forgotten a https setting?
In fact, if I turn ssl off, then itās working perfectly. And disabling basic authentication with ssl doens't solve the problem.
Thanks for help
Here are some more details:
I have a react app created with create-react-app tool.
The app call a spring-boot backend.
I use docker to run all that stuff.
I use https to prevent clear-text password of basic authentication.
I serve my app at this example name: https://myPublicHostname (on port 443)
The backend must be reachable with this name: https://myPublicHostname/rest/myapi/
Here is my deploying files structure:
WebDockerService
\-- my-react-app
\-- public
\-- src
\-- package.json
\-- default.conf
\-- Dockerfile
\-- fullchain.pem
\-- htpasswd
\-- privkey.pem
\-- my-api
\-- my-api-0.0.1-SNAPSHOT.jar
\-- Dockerfile
\-- docker-compose.yml
Here is my Docker-compose file
version: '3.1'
services:
frontendwithproxy:
build: ./my-react-app
ports:
- 80:80
- 443:443
springbootbackend:
build: ./my-api
ports:
- 8080:8080
networks:
default:
external:
name: netDev
Here is āmy-react-appā Dockerfile to build nginx server
### STAGE 1: Build ###
FROM node:9.11.1 as build
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install react-scripts -g --silent
COPY . /usr/src/app
RUN npm run build
### STAGE 2: Production Environment ###
FROM nginx:1.13.12-alpine
COPY fullchain.pem /etc/nginx/fullchain.pem
COPY privkey.pem /etc/nginx/privkey.pem
COPY default.conf /etc/nginx/conf.d/default.conf
COPY htpasswd /etc/nginx/conf.d/htpasswd
COPY --from=build /usr/src/app/build /usr/share/nginx/html
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Here is the default.conf file for nginx
server {
#To redirect http traffic to ssl
listen 80;
return 301 https://myPublicHostname$request_uri;
}
server{
listen 443 ssl;
server_name myPublicHostname;
#root containing react app files
root /usr/share/nginx/html;
#Basic authentication enabling
auth_basic "Restricted Access!";
auth_basic_user_file /etc/nginx/conf.d/htpasswd;
#SSL Settings
ssl_certificate /etc/nginx/fullchain.pem;
ssl_certificate_key /etc/nginx/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_ecdh_curve secp384r1;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA";
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
ssl_stapling on;
ssl_stapling_verify on;
#Location for springboot api
location /rest {
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forward-Proto http;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
proxy_pass http://192.168.1.125:8080;
}
}
Here is the Dockerfile for the springboot backend
FROM openjdk:8-jdk-alpine
COPY my-api-0.0.1-SNAPSHOT.jar /opt/my-api/my-api.jar
ENTRYPOINT ["/usr/bin/java"]
CMD ["-jar", "/opt/my-api/my-api.jar", "/opt/my-api/public","/opt/my-api/temp", "/opt/my-api/uploads"]
VOLUME ["/opt/my-api/public","/opt/my-api/temp","/opt/my-api/uploads"]
EXPOSE 8080
edit :
nginx is the only entry point. everything that enter has to achieve the basic authentication. I don't activate it on http, because I don't want to allow this potential leak. But basic authentication is not the problem, because when I deactivate it, the problem alway occures.
More surprising, backend "GET" queries that get pictures work fine. The pictures are well displayed. They work into markup and into browser url field.
But the other GET queries that return zip or other content-type doesn't work. (doesn't work as well in markup as when typed into the browser).
edit 2 :
In fact, it seems to work. Because when I use a rest client and query my resource on backend, the result is well arriving. Also if I call the backend in code winthin react app, the result arrives.
But when I call the backend with a href on a like this :
<a
href={"https://myPublicHostname/rest/my-api/getZipFile?value=1,2,3,4,5"}
target="_blank"
>
then the backend doesn't receive the get query.
So myabe some header are missing!?
When I query my springboot backend it works fine. The password is asked then when Iām authenticated, I receive the answer.
If the authentication is enabled on both nginx and backend , then you will need some way so that nginx can authenticate to backend.
When the nginx tries to access the backend , the backend will timeout for authentication. Maybe the auth info is encrypted and cant be taken out.
First test it with authentication on nginx only ( with SSL ) and turn of the auth on backend.
You can also try to turn off the SSL from nginx to backend.
If the above scenario is not the case , and backend has no auth and SSL then here is one answer with nginx SSL basic auth issue:
Nginx basic auth working on http but not on https
so you first need to make sure nginx is configured to ask for password on both http and https , then do the rest of work. You can just test it first on some simple page.
Problem solved like this:
<a
href="/rest/photo/getZipFile?value=1,2,3"
target="_blank"
rel="noopener noreferrer"
download="AnyCustomFileName.zip"
>
...button
</a>
This simple attribute that changes everything :
download="AnyCustomFileName.zip"
With it, the browser add different headers, then Nginx achieve to rout it at the right destination.
Works for Edge, Chrome, Samsung internet and Firefox... but Fireforx only works in private sessions.
Anyone please explain it.
I'm struggling with this.I followed this blogpost https://www.davidmeents.com/blog/how-to-simply-deploy-a-react-app-on-digital-ocean/
But all i got default page of nginx or now after some messing around with configuration i'm getting 404 not found error.
There are two floders inside nginx 1) sites-availble 2)sites-enabled
I'm not sure which one is relevant here.
my config is like this
server {
listen 80;
server_name 139.59.25.228;
root /www/mywebsite/app/build;
rewrite ^/(.*)/$ $1 permanent;
location / {
try_files $uri index.html;
}
}
Thanks -:)
It's not so complicated, you just need to:
1/ Start your react application as usual, maybe npm start, then maybe it will open port 3000 for you (or any number)
2/ Config nginx for port 80 pointing to that localhost:3000 (or your defined port):
server {
listen 80 default_server;
server_name YOURDOMAIN.HERE;
location / {
#auth_basic "Restricted Content";
#auth_basic_user_file /home/your/basic/auth/passwd_file;
proxy_pass http://localhost:3000; #or any port number here
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;
}
}
However, in order to keep the npm start - your localhost with port 3000 server always alive, I suggest you use pm2:
sudo npm install pm2 -g
Then, change directory (cd) to your reactjs app folder: (I assume you use npm start for starting you reactjs app)
pm2 start npm -- start
(if you use kind of npm run:start to start app, then it should be: pm2 start npm -- run:start)
After that, this command will be remembered by pm2!
Useful pm2 commands:
pm2 list all
pm2 stop all
pm2 start all
pm2 delete 0
(use delete 0 to delete the first command from pm2 list with ID 0)