Cannot GET etc with Nginx Reverse Proxy React + Node + PM2 - node.js

In setting up an Nginx reverse proxy for both a React app and a Node web server, it seems to have broken Express on the backend, although I can tell I'm accessing it in the browser by receiving "Cannot GET XX" messages after adding the second location block soon to follow below (previously the browser was just white when visiting the API endpoints because React Router was trying to grab them).
Here's what the config looks like, where port 3000 is my React app and 4000 is my Express server, both being managed by pm2:
server {
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name www.mywebsite.com; # managed by Certbot
location / {
proxy_pass http://127.0.0.1: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;
}
location /api/ {
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;
}
}
Simple Express route that won't work ("Cannot GET /"):
app.get('/', (req, res) => {
res.send('Hello, world!');
});
There is some additional certbot stuff that was generated for SSL, but I'm not sure it's relevant. The React app works perfectly, but whether it's "location /api/" vs "location /api" and no matter how I name my routes in Express, they all can't resolve despite having worked perfectly before. Thanks in advance for any guidance!
EDIT: I changed the server conf to at least map /api/ to my server's root with a trailing backslash so I don't have to prepend /api to every route handler, but the issue still remains ("Cannot GET /").

Why do you use the following headers?
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
Probably not needed if you are using TLS/https and it may be causing issues with express if the upgrade header exists. Try removing that.
These headers are generally used for WebSockets. See the nginx docs for more details.

Related

Node JS hosting using Nginx Reverse proxy gives 404 error

I want to host a Nodejs API server to my digitalocean server where a WordPress application is already running using Nginx and PHP fpm
I followed the below link to set up the WordPress application and it's working fine now.
https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-as-a-web-server-and-reverse-proxy-for-apache-on-one-ubuntu-18-04-server
I wanted to set up Nodejs application inside the same server for demo purposes and I followed the digitalocean guide for setting up node js with a different config file and subdomain.
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-16-04
My Nginx config for node application looks like this
server {
server_name sub.domain.com
location / {
proxy_pass http://localhost:6969;
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;
}
}
I have allowed port 6969 using ufw allow 6969.
I am able to access the Nodejs application using sub.domain.com:6969 but sub.domain.com gives me a 404 error. (404 Not Found nginx/1.18.0 (Ubuntu))
I want to access Nodejs application directly without a port number. I have checked Nginx logs and there are no errors, and configures is gives success in nginx -t
Please give me some suggestions to debug and fix this issue. I don't have much knowledge in Nginx configuration. I was just following tutorials from Digitalocean to configure the WordPress and node application.
Thanks in Advance
You are missing the port
server {
server_name sub.domain.com;
listen: 80;
location / {
proxy_pass http://localhost:6969;
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;
}

I want to deploy back-end and front-end seperate apps on the same server with nginx

I've created a restful api with nodejs and I'm planning to use sapper/svelte for front-end. In the end, these will be seperate apps and I want to run them on the same server with same domain. Is this approach reasonable? If it is, what should my nginx configuration file look like? If not, what should be my approach?
This my conf for api:
server {
server_name domain.name;
location / {
proxy_pass http://localhost:5000;
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;
}
.
.
.
}
Following best pratice your API will be under BASE/api/
That will allow you to host backend + Frontend on the same server
server {
server_name domain.name;
location /api/ { # Backend
proxy_pass http://localhost:5000;
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;
...
}
location / { # Frontend
root /app-path/;
index index.html;
try_files $uri $uri/ /index.html;
...
}
}
Since this is your first svelte / sapper project, I would keep things separate and see if you can get started with svelte to hit the API on nginx. Decouple things and ship svelte on gitlab pages or whatever other CI destination you prefer.
If it comes time to run with sapper, my advice remains the same - have it hit your API externally to keep your projects clear and distinct. You already launched the API before the front end - no worries, but I don’t see how your config needs to know where the front end will run or why entwining them would be beneficial.

Configure nginx for both Vue app front end and node.js backend

I have been searching for this answer for months and have never been able to resolve this. I am using nginx as my web server and using node.js for my backend apis and vue as my main front end webpage that uses webpack. I would like to be able to go to my Vue page by going to http://ip and then get access to the api services by going to http://ip/api. I dont have a domain name set up so I use IP address for the urls.
So far I built my Vue app and is sitting in the /var/www/html/Web/dist folder and it works if you go to the http://ip url but I can not access my node.js APIs. My node.js server is running on localhost port 3000. My nginx config looks like this:
server {
listen 80;
root /var/www/html/Web/dist;
}
server {
listen 80;
location /api/ {
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;
}
}
You are duplicating server configuration. Simply keep one server properties set :
server {
listen 80;
root /var/www/html/Web/dist;
location /api/ {
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;
}
}
That means :
listens to all request for all ip's on port 80
Evaluate relative path from root /var/www/html/Web/dist;
if there's a matching '/api/' in url pass it to localhost:3000
It should work as expected now

Nodejs (sailsjs), NGINX and sails.io (socket.io)

I'm using NGINX to handle my Nodejs servers and now I want to start using socket.io on them, doing research before starting to play with socket.io i found Sailsjs which I grew rather found of and now currently using.
The problem I meet though, is that the client can't connect through NGINX on socket.io, or sails.io.
This is the URL path for my current APP:
https://localhost/economy
And the url for sails.io is, as standard:
https://localhost/economy/assets/js/dependencies/sails.io.js
Now!
Using FileSeek I found out where sails.js use "require("socket.io")", which is in the "loadSocketIO.js" (node_modules\sails\lib\hooks\sockets\lib). I edited the file to say:
var io = sails.io = sails.ws =
SocketServer.listen(sails.hooks.http.server, {
resource: 'economy',
logger: {
info: function (){}
}
});
adding the resource: 'economy', line.
Then on the client side I did the same:
var socket = io.connect('https://localhost/economy/socket.io', { resource: 'economy' });
I've been playing with this and tried different ways, like "economy/socket.io", the full socket.io path etc.
Any help, is a lot of help!
I've been struggling for a day now so I figured i'd ask for some help :)
You shouldn't need to change anything on the Sails side. Try reading up on proxy_pass for your location directive in Nginx.
http://nginx.org/en/docs/http/websocket.html
This is an excerpt from the above link:
location /chat/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
SOLUTION!
Run everything as it is, the only part you have to edit is in NGINX.
set a server block with the servername as economy.localhost/, and you're done :)
Remember to link economy.localhost to 127.0.0.1 or set a cname if this is a production server :)
The example showed here worked for me.
Basically for nginx WebSocket support you need to include the following config.
server {
server_name app.domain.com;
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:8080;
}
}

Making ExpressJs recognise base path

I have built an small nodejs app using express. Everything works fine on my local machine & the app runs good when I point my browser to http://localhost:3000
But now I am planning to host this app on one of the domain, Lets say http://example.org which is running on nginx & its a php code
But how do I make my express app to properly run the app on example.org/nodeapp ?
Currently, it is considering the example.org as base url of my app & hence throws 404 as it searches for nodeapp in my routes. It should ideally consider example.org/nodeapp as baseurl.
In my server block config, I have following code
listen 80;
server_name your-domain.com;
location /nodeapp {
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;
}
You could have nginx rewrite the url by adding something like rewrite ^/nodeapp/(.*) /$1 break;

Resources