Nginx with Frontend and Backend Server - reactjs

I'm working on a CTF that will be downloaded and run locally on a VM. The IP address of the CTF will be different for each user. I have a frontend server (React.js) running on port 3000. I'm making a request like so to the backend server:
fetch("http://localhost:5000/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
The backend server (express.js) is running on port 5000. I have nginx configured to route port 3000 request to port 80.
listen 80 default_server;
listen [::]:80 default_server;
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;
}
When the CTF is booted a user will get a private IP like so: 192.168.2.136. My question is, how do I make request to the backend because fetch("http://localhost:5000/login) will not fetch from the backend. I will need to do fetch("http://192.168.2.136:5000/login for it to work. Can this issue be resolved with nginx, or will I need to look into a way to get the private IP address when the VM boots?

For anyone with the same issue, I fixed it by using a server name in nginx and properly routing the backend traffic to my backend server like so:
server {
listen 80;
server_name resume.tm;
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;
}
location /api/ {
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;
}
}

Related

How to host multiple create-react-app development servers under nginx with working live (hot) reload

I am developing a website with React.js for the frontend and have 2 separate apps for the users and the admins. The users will be under example.com and the admins under example.com/admin.
I am developing both apps behind an nginx server as a reverse proxy. I have had no issue developing a single app behind nginx, but I cannot use hot reload for the 2nd app. The app is served properly, with the only exception that the hot reload does not work.
I have HTTPS=true on both my .env files of the React.js apps. The main app's hot reload works fine, but the /admin app's hot reload fails with the error Firefox can’t establish a connection to the server at wss://192.168.1.2/adminws (developing through local network, so I can test the apps on my phone as well, but the hot reload won't work on the localhost either).
The main app is hosted under port 3000, the admin app is hosted under port 4000.
This is what my main app's .env looks like:
HTTPS=true
WDS_SOCKET_PORT=443
FAST_REFRESH=true
This is what my admin app's .env looks like:
HTTPS=true
WDS_SOCKET_PORT=443
WDS_SOCKET_PATH=/adminws
FAST_REFRESH=true
This is what my nginx configuration file looks like:
server {
# listen 80 default_server;
# listen [::]:80 default_server;
# SSL configuration
#
listen 443 ssl http2 default_server;
listen [::]:443 ssl default_server;
ssl on;
ssl_certificate /etc/nginx/ssl/localhost.crt;
ssl_certificate_key /etc/nginx/ssl/localhost.key;
gzip on;
gzip_types text/plain application/xml application/json;
gzip_proxied any;
gzip_min_length 1000;
gunzip on;
gzip_static on;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location /ws {
proxy_pass https://127.0.0.1:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
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 /adminws {
proxy_pass https://127.0.0.1:4000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
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:3200;
}
location /admin {
proxy_pass https://127.0.0.1:4000;
}
location / {
proxy_pass https://127.0.0.1:3000;
}
}
I should note that the admin app's hot reload works properly when I remove both WDS_SOCKET_PORT and WDS_SOCKET_PATH from the .env file and run it on https://localhost:4000/admin, but this way I would not be able to test it behind nginx.
I removed both WDS_SOCKET_PORT and WDS_SOCKET_PATH from the admin app's .env file and it now seems to be working properly. Everything else seems to be ok.

Websocket with nginx proxy

I'm having issues with getting the websocket connected properly with nginx proxy. If I add the port to the use effect it does connect properly.
Here's the react side.
useEffect(() => {
console.log('web socket')
const socket = new WebSocket(`ws://${window.location.hostname}/websocket`);
socket.onopen = () => socket.send('Connected to React')
setSocketIo(socket)
}, [])
Here is the nginx config snippet
location /websocket/ {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
This is error I get in the console.
WebSocket connection to 'ws://localhost/websocket' failed:
Error from nginx logs
2022/04/13 13:23:42 [error] 16848#8212: *1499 connect() failed (10061: No connection could be made because the target machine actively refused it) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /socket.io/?EIO=4&transport=polling&t=O0ac97J HTTP/1.1", upstream: "http://[::1]:3000/socket.io/?EIO=4&transport=polling&t=O0ac97J", host: "localhost", referrer: "http://localhost/guac"
Is it automatically adding the socket.io to the end of hostname?
I use django-channels, and this is my working nginx settings, Hope this helps you. By the way, I'm still not using this in production but this works in development. You can configure to use WebSocket with WSS and that's all.
upstream channels-backend {
server localhost:8000;
# here you connect your channel ip:port
}
server {
server_name example.com www.example.com;
location /static/ {
}
location /media {
}
location / {
include proxy_params;
proxy_pass http://unix:/yourGunicorn.sock;
# This is for Nginx connection to gunicorn
}
location /ws/ {
try_files $uri #proxy_for_websocket;
# websocket connection comes with ws
}
location #proxy_for_websocket {
proxy_pass http://channels-backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
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_set_header X-Forwarded-Host $server_name;
}
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
# Your certificate detail here
}
from javascript, you are trying to connect with
const socket = new WebSocket(`ws://${window.location.hostname}/websocket`);
ws protocol and in your nginx you are writing
location /websocket/ {
---
---
}
which is totally wrong. This should be -
location /ws/ {
---
---
}
Hope this helps :)

Accessing http://example.com gives 502 Bad Gateway But http://example.com:3000 gives me the website

I have a reactJS app running at port 3000 on a VPS. I am having difficult understanding why http://example.com is not working while http://example.com:3000 is working correctly. Below I have my nginx server configuration
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
# Enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
}
}
Is there anything i missed? Thank you!

AWS front-end back-end communication

I have 2 apps running on ASW Symfony on port 8000 (local) and react 3000(local) but accessible through TCP on port 80 redirections was achieved by listening of port 80 within nginx server.
server {
listen 80;
server_name example.info www.example.info;
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;
proxy_redirect off;
}
}
server {
listen 8000;
server_name example.info www.example.info;
location / {
proxy_pass http://127.0.0.1:8000;
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;
proxy_redirect off;
}
}
I have tried to listen and redirect of two ports but without success.
Within the server, Symfony application is accessible with curl http://127.0.0.1:8000
From outside in my react app I am sending api requests to asw.external.ip (123.123.123.123:800) but I get timeout. How could I access my back-end from outside?
AWS ElasticBeanstalk - Configuring the Proxy Server to your back-end
You can use this config file to your Aws Ec2 as well.
/etc/nginx/conf.d/proxy.conf
upstream nodejs {
server 127.0.0.1:5000;
keepalive 256;
}
server {
listen 8080;
access_log /var/log/nginx/access.log main;
location / {
proxy_pass http://nodejs;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
## Optional configuration if you want to allow AWS
## to cache your static files
location /static {
alias /var/app/current/static;
}
}
Edit - Configuring Nginx for Symfony
server {
listen 8080;
server_name sf2testproject.dev;
root /home/maurits/public_html/web;
location / {
# try to serve file directly, fallback to rewrite
try_files $uri #rewriteapp;
}
location #rewriteapp {
# rewrite all to app.php
rewrite ^(.*)$ /app.php/$1 last;
}
location ~ ^/(app|app_dev|config)\.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
Where:
listen is the port that your application communicate with the world.
fastcgi_pass is a binary protocol for interfacing interactive programs with a web server
References:
Aws ElasticBeanstalk - Nodejs platform proxy
Symfony Hhvm 3 nginx 1.4 vs PHP 5.5 apache 2.4
FastCGI Oficial Example

ExpressJS/NodeJS - Reverse Proxy Deployment

I have 3 AngularJS application each having their own ExpressJS backend. How do you deploy all 3 applications in this manner:
http://myapp.com/<app1>
http://myapp.com/<app2>
http://myapp.com/<app3>
Additional Information:
- I'm deploying the application in AWS EC2 Instance
- I tried merging the application in a single ExpressJS app. While this works, I still want to know if the case above is possible
Sure it's possible. You'll just need NGINX or Apche running as a reverse proxy for you.
Assuming your node apps are running on local ports 3000, 3001, and 3002, you'd setup a .conf file with those as upstream servers for the location tags like so:
. . .
location /app1 {
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;
}
. . .
location /app2 {
proxy_pass http://localhost: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;
}
}
Read up on more details here: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-16-04
server {
listen 80;
server_name es.domain.com;
location /app1 {
rewrite ^/(.*) /$1 break;
proxy_ignore_client_abort on;
proxy_pass http://localhost:3001;
proxy_redirect http://localhost:3001 https://es.domain.com/appw;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
auth_basic "Elasticsearch Authentication";
auth_basic_user_file /etc/elasticsearch/user.pwd;
}
location /app2 {
rewrite ^/(.*) /$1 break;
proxy_ignore_client_abort on;
proxy_pass http://localhost:3002;
proxy_redirect http://localhost:3002 https://es.domain.com/app2;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
auth_basic "Elasticsearch Authentication";
auth_basic_user_file /etc/elasticsearch/user.pwd;
}
}
Please refer this link
http://www.minvolai.com/blog/2014/08/Setting-up-a-Secure-Single-Node-Elasticsearch-server-behind-Nginx/Setting-up-a-Secure-Single-Node-Elasticsearch-server-behind-Nginx/
You can setup AWS CloudFront and setup each application as Origins. It provides flexibility to route from single domain(Setup for CloudFront) to different Express Apps and also allows to cache Static content paths at Edge locations.

Resources