I’m deploying my first Node.js / React / MySQL app. I decided to deploy it on a VPS server from Hostinger (first time I’m using a VPS).
I followed some tutorials to set up the server with Nginx. I cloned my repo, build the front and now both front and back are online, but they won’t communicate together (every request from client to server returns a 404 error.)
In development everything was working fine. I use Axios to make fetch requests. They were communicating through a proxy ("proxy": "http://localhost:4000" in package.json of frontend. I removed this line in production)
My Nginx config for backend:
server {
server_name api.mywebsite.com www.api.mywebsite.com;
location / {
proxy_pass http://127.0.0.1:4000;
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;
}
}
and for frontend:
server {
listen 80;
listen [::]:80;
root /var/www/mywebsite/frontend/build;
index index.html index.htm;
server_name shop.mywebsite.com www.shop.foryoumaquillage.fr;
location / {
try_files $uri $uri/ =404;
}
}
Those config are in different files, in /etc/nginx/sites-available folders with links to /etc/nginx/sites-enabled/ folder. I tried to put the config in a unique file but it didn’t work.
For info here is my frontend package.json:
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@paypal/react-paypal-js": "^8.1.1",
"@redux-devtools/extension": "^3.2.5",
"@reduxjs/toolkit": "^1.9.5",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"ag-grid-community": "^30.0.3",
"ag-grid-react": "^30.0.4",
"axios": "^1.4.0",
"bootstrap": "^5.2.3",
"bootstrap-icons": "^1.10.5",
"react": "^18.2.0",
"react-bootstrap": "^2.7.4",
"react-dom": "^18.2.0",
"react-helmet-async": "^1.3.0",
"react-image-gallery": "^1.2.11",
"react-multi-carousel": "^2.8.4",
"react-redux": "^8.1.1",
"react-router-bootstrap": "^0.26.2",
"react-router-dom": "^6.11.1",
"react-select": "^5.7.3",
"react-simple-star-rating": "^5.1.7",
"recharts": "^2.6.2",
"rsuite": "^5.33.1",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"react-scripts": "5.0.1"
},
"scripts": {
"start": "set PORT=3005 && react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
and package.json for backend:
{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"server-prod": "node server.js",
"server-dev": "npx nodemon server.js",
"client": "npm start --prefix ../frontend",
"dev": "concurrently --kill-others-on-fail "npm run server-dev" "npm run client""
},
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-fileupload": "^1.4.0",
"express-rate-limit": "^6.8.1",
"helmet": "^7.0.0",
"jsonwebtoken": "^9.0.0",
"mysql2": "^3.3.3",
"node-fetch": "^2.6.12",
"uuid": "^9.0.0"
},
"devDependencies": {
"concurrently": "^8.2.0",
"nodemon": "^2.0.22"
}
}
What I tried:
I tried to change Axios configuration using the following:
import axios from 'axios';
export const AxiosRequest = axios.create({
baseURL: process.env.API_URL,
});
and I use AxiosRequest for all my fetch requests (API_URL=http://127.0.0.1:4000)
I installed cors (which I didn’t use in development) to try to fix my problem but it didn’t work. For now it allows requests from everywhere.
app.use(cors())
I tried to change Nginx config following old Stackoverflow solutions (for example make my backend listen to 3005) but nothing work (usually the changes I tried just make my api unaccessible…).
As said it’s the first time I’m deploying a "complex" app like this one, and first time I’m using a vps / nginx. So I might have made a rookie mistake either in my code or setting up my Nginx server
edit
Precisions on how I deploy my app:
I bought a domaine name via hostinger and created 2 DNS records: both are type A, point to the same ip address and with TTL 14400. One is named api.mywebsite.com, and the other one is shop.mywebsite.com (the name is the only difference).
On my server, in directory /var/www/ I created a new directory for the app, and inside it I have the backend directory and the frontend one.
2
Answers
I'm not sure what was wrong but I decided to delete my repo and server config files, and redo everything.
I chose this time to build the frontend, move the file to the backend directory, and only run my backend, by modifying
app.use(express.static(...))
function in the server.js file.For now, my config file is very simple, and might need some improvement:
And I changed my DNS settings.
Now everything seems to work properly.
cUrl
or communicate with the API server without the web page? Get the API server working independently.Some other thoughts:
I have my front-end and API running on the same server, with a single nginx. The root of the default nginx (port 80) is to the root of the client distribution, and any path to
/api
is for the "api server" and routed to nodejs with the same proxy-pass you set up. I’m deployed on AWS and the 443 forwarding is happening outside of my server (at the load balancer) so my server is really only listening to 80.I set up my nginx
proxy-pass
like this:and at the same level as
server
defined theupstream
(you can ignore the keepalives)