Nginx With SSL and Frontend + Backend same server - node.js

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;
}

Related

ReactJS with Nginx 404 Not Found when entering a specific url path

What I am trying to do is to prepare this machine to serve my web application. It works without any problems when I serve it via npm start.
I have a domain, let's say, example.com on which I installed SSL with Certbot and have successfully rerouted http to https with www.example.com and example.com.
Now what happens is when I go to www.example.com or example.com it works fine, and I can move to whatever url path I want, as long as it is directly accessed from any button on the homepage, but whenever I try to access an individual url path, let's say myexample.com/admin/login (it is hidden from the homepage) or any manually entered url path, the webserver returns error 404. This does not happen when I do the same with npm start.
I am running an EC2 machine with the following components installed:
Operating System: Ubuntu 20.04 LTS
Webserver: Nginx 1.18
Node: 10.24.1
NPM: 6.14.12
SSL Provider: Let'sEncrypt (Certbot 0.40.0)
I have the following ports open from the EC2 Management Console:
80/custom anywhere (http)
443/custom anywhere (https)
22/custom my IP (ssh)
3000/Custom my IP (npm start default port)
I have also allocated an Elastic IP to my machine, let's say it's 1.1.1.1 .
My Nginx config file is located at:
/etc/nginx/sites-enabled
and is called: client-config
I have set up my Nginx config to look like this:
server {
server_name 1.1.1.1 example.com www.example.com; # 1.1.1.1 this is an example ip
root /home/ubuntu/app-deploy/build;
index index.html; # react by default generate the file in the build directory
location / {
try_files $uri $uri/ =404;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.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 = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name 1.1.1.1 example.com www.example.com; # 1.1.1.1 this is an example ip
return 404; # managed by Certbot
}
Running nginx -t returns:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

ReactJS Router Dom not navigating to dashboard after logging in

Please help. I have my ReactJS NodeJS deployed on Linux NGINX and I can login on my development machine, on my phone, and on Linux OS running on my computer Oracle VM; i can accessed the application on these devices and it worked fine even when I changed IP address but immediately another device e.g somebody else computer or phone tries to login, it would always not redirect to dashboard but my three devices(laptop, phone, and Linux OS running on my computer Oracle VM) can redirect successfully to dashboard after logging in.
I have tried everything on this page below that people provided as solution but to no success :
https://stackoverflow.com/questions/43951720/react-router-and-nginx
Infact, i don't even see their login attempt in the NodeJS API running. My ReactJS build file contents are in /etc/nginx/sites-available/mydomain/ and this is my nginx.config below:
user www www; ## Default: nobody
server { # simple reverse-proxy
listen 80;
server_name mydomain;
# serve static files
#location ~ ^/(images|javascript|js|css|flash|media|static)/ {
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
root /etc/nginx/sites-available/mydomain;
index index.html;
try_files $uri /index.html;
}
location /api {
proxy_pass https://localhost:8084;
root /etc/nginx/sites-available/mydomain;
index index.html;
}
}
server {
listen 443 ssl;
server_name mydomain;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
root /etc/nginx/sites-available/mydomain;
index index.html;
try_files $uri /index.html;
}
location /api {
proxy_pass https://localhost:8084;
root /etc/nginx/sites-available/mydomain;
index index.html;
}
ssl_certificate /etc/letsencrypt/live/mydomain/fullchain.pem; # managed by Certbot;
ssl_certificate_key /etc/letsencrypt/live/mydomain/privkey.pem; # managed by Certbot
#...
}
Please fams, what difference does it make as I have my NGINX configuration in nginx.conf and not default?
As I configured my nginx.conf do I still need to go do the same in /etc/nginx/sites-available/default and what extension is this default config file?

Nginx reverse proxy to node application API

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 /

NginX : Serve static content and proxy pass to Node API

I'm running a website composed of an API in a docker on port 8080, and a static folder containing the front-end react app.
The api is at /api
I'm trying to configure NginX to correctly serve this configuration, but I can't seen to figure out how to have both working.
If I setup my default like this:
server {
root /var/www/html;
server_name DOMAIN; # managed by Certbot
location #nodeapp {
# Redirect to the api
proxy_pass http://localhost:8080;
}
location / {
# Map all the routes to the index.html
try_files $uri #nodeapp;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/DOMAIN/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/DOMAIN/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
}
Then everything is redirected to my API, and the static content is not delivered if not explicitly specified (e.g. going to https://host/index.html)
If I add try_files $uri $uri/ #nodeapp; to serve the root folder as a directory, the index gets served, but I can't access the API anymore, it always serve the react app
I also tried to add
location /api/ {
proxy_pass http://localhost:8080
}
But no difference
What am I doing wrong ?
I found the answer, the react app I was using was setup with a service worker, which was messing with the routing. I removed it and it works like a charm now !

Set up nginx and node apps on ubuntu

Here's the situation -
node express app1 (backend app - REST API server) - running on port 8888 -
bunch of POST routes (auth, api, download, upload..) - communicating with mysql server - maintained by developer #1
node (webpack, react) app2 (front end app) running on port 80 - maintained by developer #2
This week we set up nginx and HTTPS (via Let's encrypt), which means that when a user comes to the www.oursite.com - it is redirected to the https site with nice green lock and secure site. So far so good. However, when the user enter her email, the app2 is supposed to call app1 and email with registration token should be sent. This worked well before we try to set up nginx - and use http on both apps. Now this call is not happening. This is our nginx setting:
server {
listen 80;
listen [::]:80;
root /var/www/oursite.com/html;
index index.html index.htm index.nginx-debian.html;
server_name oursite.com www.oursite.com;
location / {
try_files $uri $uri/ =404;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/oursite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/oursite.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
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
# Redirect non-https traffic to https
# if ($scheme != "https") {
# return 301 https://$host$request_uri;
# } # managed by Certbot
}
My question (developer #1) - should I replace all routes in my app (backend app - app1 - backend) to be https instead of http? Apparently Chrome is not calling http request from https site (as is our case)
and how should I setup the nginx then - I belive I should add another location part in nginx setting.
If there are other suggestions please let us know.
Each port must get its own server{ } block, so port 80 gets one and port 443 get another each with a listen directive to the respective port ... in above you have both ports in the same server{ } block
If the app is exposed to the internet they should be using https and if not their incoming traffic using http which is port 80 block must get redirected to send traffic to 443 ... so your nginx config file will look similar to
server {
listen 80 ;
listen [::]:80 ;
server_name example.com, www.example.com;
# Redirect all HTTP requests to HTTPS
rewrite ^/(.*) https://example.com/$1 permanent;
}
server {
listen 443 ssl ;
listen [::]:443 ssl ;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/oursite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/oursite.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
location / {
# direct traffic to my server on its host IP and port
proxy_pass http://172.19.0.5:3000/; # notice http not https
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}
In your case looks like app1 is not exposed to the internet and so does not appear in your nginx config ... it only receives http traffic downstream from app2 ... all of above config is only for your app2 ... incoming internet traffic using secure https port 443 (or port 80 which gets redirected to 443) receives what is called TLS termination ... apps shielded from the internet by the nginx TLS termination receive http traffic not https which is fine since the app ports are not visable from the internet ... and so your app2 gets http traffic not https
We got this to work by setting the app1 (backend up) as https as well. However, this works in all major browser, except for firefox. SO I guess I shiuld post a new question now. The site is not letting through the form on firefox - but only if the address does not have www. That means https://testsite.com -> not working, https://www.testsite.com working ok. But is working ok on all other browsers.

Resources