Nginx reverse proxy to node application API - node.js

I've got an NGINX reverse proxy on my server handling requests for http://apcompdoc.com. It listens on port 80, and can successfully return the Vue Dist, however, I have a backend node API running on port 8081 and another node process running on port 8082. The user never directly requests anything on 8082, but rather the process on 8081 sometimes requests the process on 8082, so I'm assuming I never have to even expose that to Nginx at all, but I'm not too sure. However, the main problem is that the API is never reached I believe. I have it so that when you hit the endpoint http://apcompdoc.com/api/* it should proxy over to the node process. I am using PM2 to keep the process alive and monitor it, and am assured it's running. This is my NGINX apcompdoc.com config file:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name: apcompdoc.com www.apcompdoc.com;
charset utf-8;
root /var/www/apcompdoc/dist;
index index.html index.htm;
# Always serve index.html for any request;
location / {
root /var/www/apcompdoc/dist;
try_files $uri /index.html;
}
location /api/ {
proxy_pass http://localhost:8081;
}
error_log /var/log/nginx/vue-app-error.log;
access_log /var/log/nginx/vue-app-access.log;
}
I am trying to get all requests to my API at /api/* to get redirected to the API at localhost:8081 and then returned to the user. I saw something about redirecting the proxy back, do I have to do that? I also don't know if I have to do /api/* in the NGINX config file.
I'm really new to NGINX but I just want the requests to http://apcompdoc.com/api/* to be redirected to the node process on port 8081.

Bad or good practice, I'm not sure, but I always defining my backend as upstream.
For example, your file will look like this:
upstream nodeprocess {
server localhost:8081;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name: apcompdoc.com www.apcompdoc.com;
charset utf-8;
root /var/www/apcompdoc/dist;
index index.html index.htm;
# Always serve index.html for any request;
location / {
root /var/www/apcompdoc/dist;
try_files $uri /index.html;
}
location ^~ /api {
proxy_pass http://nodeprocess;
}
error_log /var/log/nginx/vue-app-error.log;
access_log /var/log/nginx/vue-app-access.log;
}
Please note I added ^~ in the location of the api and removed the trailing /

Related

Nginx With SSL and Frontend + Backend same server

I have a server (VPS Amazon) with Ubuntu. In this server is running my backend node and my frontend React.
My ReactApp is running over nginx and my backend over pm2.
In my react app I defined REACT_APP_BASE_URL: http://[my_ip_server]:4000.
So everything was working OK but after I configured SSL in nginx, I can access my frontend login page but when I send the request, I catch the following errors:
a) If I set https in my REACT_APP_BASE_URL (https://[my_ip_server]:4000), I get this error: ERR_SSL_PROTOCOL_ERROR.
b) If I let with http, I get Mixed Content error
Someone know How I do this work?
Thanks a lot!
My nginx.conf. At moment I'm using just port 80 until I solve my problem.
server {
#listen [::]:443 ssl ipv6only=on; # managed by Certbot
#listen 443 ssl; # managed by Certbot
#ssl_certificate /etc/letsencrypt/live/mysite.com.br/fullchain.pem; # managed by Certbot
#ssl_certificate_key /etc/letsencrypt/live/mysite.com.br/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
#if ($host = surveys.alcancenet.com.br) {
# return 301 https://$host$request_uri;
#} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name mysite.com.br;
#return 404; # managed by Certbot
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri /index.html;
}
}
With help from #Markido. I managed to solve that.
I added in my backend the default route "/api" and after that I put in my nginx config the following
location /api {
proxy_pass http://localhost:4000;
}
Tks!!!
First off, there is a difference between running the applications (which is what i assume you are using PS2 for), and exposing them through an nginx proxy.
It would be most helpful to show us your nginx config file, and also tell us which port your backend runs on (assuming the frontend runs on port 4000).
Edit;
Thanks for the config and backend port.
I don't think you need to set the create react app base url to https, just set the port and run it on the VPS using PS2.
I can't see how you have any proxy at all pointing to 4000 in your config - do you not expose the backend?
The only exposed part is static html files. The relevant code is;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri /index.html;
}
If you want to call the backend using https, or generate your site using some tool with a process which entails HTTPS calls, you need to do so correctly in the frontend. IE something doesn't add up here.
The usual approach is;
Expose the backend and the frontend on port 443 SSL only, using different sub-domains (eg. api.mydomain.com), and then use the proxy in nginx to redirect 443 traffic for each domain to the corresponding local ports (4000, and the frontend port or static files directory more likely).
Instead of:
location / {
try_files $uri $uri /index.html;
}
Use something like:
location / {
proxy_pass http://localhost:4000;
}

How do I Run React App on Nginx with a node.js backend on AWS EC2?

I am trying to run a react app with Node.js backend on the Nginx server.
Here's my server block in the nginx.conf file:
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/folder-name/frontend/build;
index index.html index.htm;
location / {
proxy_pass http://localhost:5000;
}
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
The build folder contains the compiled react js code(using npm run build)
Node.js backend is running on port 5000 using pm2/forever.
After restarting the Nginx Server, the react UI appears on the server IP but the UI is distorted.
Also, I am not able to access my backend APIs on MyIP/api/endpoint.
What am i doing wrong.? This nginx configuration was built from SO and other online resources so there's a huge probabilty that it could be wrong. Please help!
Thanks in advance!
The issue is you are setting the API proxy for the root (/). The correct one should look like this:
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/folder-name/frontend/build;
index index.html index.htm;
location /api {
proxy_pass http://localhost:5000;
}
location / {
try_files $uri $uri/ =404;
}
}
If you don't have /api path in your Node.js, you will need a rewrite rule for it like this:
location /api {
rewrite ^/api/?(.*) /$1 break;
proxy_pass http://localhost:5000;
proxy_redirect off;
proxy_set_header Host $host;
}
I had experience that.Please check my image file
This configuration is running successfully on aws.
Your mistakes is proxy area. Please change like that.
location /api/ {
proxy_pass http://127.0.0.1:5000/api/
}
If you want, I can HELP you.
Yes, you can host both API and static files (build files of your front-end) on the same domain or host. Below, you can find a server block for a sample API hosted on port 3000 and static HTML files at a root location being served on port 80.
server {
listen 80;
server_name localhost;
location / {
root /var/www/html;
index index.html;
error_page 404 index.html;
}
location /api/ {
proxy_pass http://localhost:3000/;
}
}
You can access the front-end at http://localhost/<blah...> and the API at http://localhost/api/<blah...> (please note how /api is handled in the URL here and the server block above). Replace localhost with your domain name.
What am i doing wrong.?
One issue is with your proxy_pass directive. You are missing trailing slash /
...
location / {
proxy_pass http://localhost:5000/;
}
...
First, try this and share your result.

Why does nginx reverse_proxy on my react app return a 404 when searching a path?

I have an nginx server with a reverse proxy pointing to my react app. The page loads fine and the links to different paths work fine when pressing through the page. However when I manually type out the url with path, I get a 404 error. Its the same path as via clicking links but I get a 404.
Here's my nginx conf file:
server{
listen 443 ssl;
listen [::]:443 ssl;
server_name sub.*;
location / {
proxy_pass http://127.0.0.1:8080;
}
// I tried adding an explicit path:
location /about{
proxy_pass http://127.0.0.1:8080/about;
}
//
// SSL Cert stuff here...
//
}
I have a similar issue with my nodejs on reverse proxy where the main url works fine but anything with a path returns a 502, but thats a separate question.
I found the solution. I had to update my nginx config to this:
server{
listen 443 ssl;
listen [::]:443 ssl;
server_name sub.*;
location / {
proxy_pass http://127.0.0.1:8080;
}
// I have to route each of my paths to my servers root
location /about{
proxy_pass http://127.0.0.1:8080;
}
location /contact{
proxy_pass http://127.0.0.1:8080;
}
// ...etc
//
// SSL Cert stuff here...
//
}
However this solution is a pain so I will be pursuing a different hosting strategy altogether.

Why proxy_pass in nginx is not working as expected?

I have following nginx configuration:
server {
listen 80;
listen 8080;
server_name localhost;
location / {
root /telly_platform/frontend/public/pwa;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://localhost:3030$request_uri;
}
}
When I perform a request to http://localhost/api/path/resource the request goes OK - where it needs to go - http://localhost:3030/api/path/resource.
But when I perform a request to http://localhost:8080/api/path/resource (with port 8080) the request is not passed to the URL in proxy_pass directive, but is processed by first location block which returns index.html content.
What am I doing wrong and how to configure nginx to return API response even if it goes through 8080 port?
Thx!

nginx default to php if node not available?

I want to default to a php application if the node applications are not currently responding to requests. (i.e. down).
What do I do?
Below is my nginx config
upstream my_servers {
least_conn;
#ip_hash; # ensures persistence of session id across servers
server 127.0.0.1:3001; # httpServer2 listens to port 8001
server 127.0.0.1:3000; # httpServer1 listens to port 8000
server 127.0.0.1:80; <---- THIS ONE IS THE PHP APP
#this could also be entirely a different host server
#Ex. server 113.333.123.190:8000;
}
server {
listen 80;
server_name weburl.com;
root /home/vince/Documents/weburl/static_php_player;
index index.php index.html index.htm;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
include snippets/fastcgi-php.conf;
}
}
Add the backup option to the php server, otherwise all the petitions will be handled by the 3 servers
upstream my_servers {
least_conn;
#ip_hash; # ensures persistence of session id across servers
server 127.0.0.1:3001; # httpServer2 listens to port 8001
server 127.0.0.1:3000; # httpServer1 listens to port 8000
server 127.0.0.1:80 backup; <---- THIS ONE IS THE PHP APP

Resources