NginX : Serve static content and proxy pass to Node API - node.js

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 !

Related

nginx letsencrypt https redirect with express nodejs app not working

I need https to be the default way my site is served, I chose option 2 during letsencrypt cert generation.
I have https working on my site. It is a simple HTML page being served up by nodejs on port 3000. It is hosted in Oracle Cloud currently. I have opened the ports in iptables as Oracle does not use ufw.
If I go to https://www.example.com , the site loads securely so things are working.
If I go to http://www.example.com, the site also loads but not securely obviously.
If I go to example.com, the site loads in http, not https.
I am having trouble wrapping my mind around how I should write my nginx config file.
I need to proxy_pass using http to port 3000, but when I change the proxy_pass to https
proxy_pass https://localhost:3000;
It fails to load anything and that somewhat makes sense to me because my nodejs app does not have any code to support https and I was under the impression that nginx can handle all of that for me. That line of thinking is further supported because like I said above, https://www.example.com works just fine for my site now.
Below is my config with my server name removed. Please let me know how to best do what I am trying to accomplish.
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:3000;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
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;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}```
Thank you to Marc, it seems like my config was created strangely and certbot added in things slightly out of order to where it was getting confusing but I have figured it out. Like Marc said, redirect all 80 to https. In https server, make sure you have your certificates and proxy_pass there to your port 3000, or wherever your app is running.
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com;
}
server {
listen [::]:443 ssl ipv6only=on; # managed by Certbot
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
location / {
proxy_pass http://localhost:3000;
}
}

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 setup NGINX for both Angular and Node?

I'm currently trying to host both an angular app and a reverse proxy to a node backend. Using Lets Encrypt, I've been able to set up the Angular app without any problems. However, I'm lost on how to configure Nginx to also act as a reverse proxy to my node app running on a specific port. I find examples of reverse proxies for nginx, but nothing that incorporates both.
Here is my config that is working with angular:
server {
server_name example.com;
root /var/www/example.com;
index index.html index.htm;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.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
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
What I'm trying to add:
server{
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
I've tried several combinations of server blocks and location blocks, but I simply get a 404 when I go to api.example.com.
I usually solve that kind of issue like this.
Endpoints of all back-end APIs are started with "v1".
I serve the angular project using pm2.
location / {
proxy_pass http://localhost:3000;
...
}
location ~ ^/(v1)/ {
proxy_pass http://localhost:3001;
...
}

POST requests to Node.js app behind nginx not getting through

POST requests to http://mysite.io:5003/GetProjects, works fine(http). But POST requests to https://mysite.io:5003/GetProjects returns 'Could not get any response' in Postman and 'ERR_CONNECTION_REFUSED' on my site at http://mysite.io/Projects. I'm using PM2 to run my backend.js and am also just running node backend.js to debug. OS is Ubuntu 16.04 in a EC2 instance, which has port 443 open.
nginx config is:
server {
listen 443 ssl;
server_name mysite.io www.mysite.io;
root /var/www/html/mysite-service/build;
location / {
proxy_set_header X-Forwarded-Proto $scheme;
try_files $uri /index.html;
}
ssl_certificate /etc/letsencrypt/live/mysite.io/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.io/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
}

NGINX SSL Configuration Ignoring API Location Block

I recently have been trying to use Let's Encrypts SSL service to upgrade my web application to https. My application is a React front-end that runs in the same AWS instance as an Express backend/api.
I've been unable to get the https version of the site working, as it makes requests to the non-SSL certified Express server effectively locking the https version of the site from using the backend.
My solution around this has been to try to configure an NGINX block to proxy the Node.js server. My NGINX configuration isn't complicated and looks like this:
server {
listen 443 ssl default_server;
server_name example.site.com;
root /home/ubuntu/react/build;
ssl_certificate /etc/letsencrypt/live/example.site.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.sitecom/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 /api/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://localhost:3050/; //port where API runs
}
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control public;
expires 1d;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.site.com;
return 301 https://$host$request_uri;
}
This setup worked perfectly when I was running an http version, but seems to have completely broken down for https. NGINX seems to be completely ignoring the /api location block - whenever I try to directly navigate to an /api endpoint it redirects me to the location block below (the static file that serves the react application). I've fiddled around with all kinds of settings and can't for the life of me figure out why NGINX isn't taking the /api location block into account, or why the SSL certification would have changed how it moves through/reads the blocks.

Resources