varnish, nginx, & node.js: static nginx html pages with node.js fallback - node.js

am running varnish on EC2 in front of nginx which routes to node.js.
What I would like is to serve specific static HTML pages from certain routes (like, / for index.html) via nginx, but have all other routes be handled by node.js.
As an example, / would be sent by nginx in the form of a static HTML page, while anything not matching, say /dynamic_stuff or /dynamic_stuff2, would be processed by node.js.
In other threads online, other people were putting node.js in a separate dir entirely, like /node/dynamic_stuff but I didn't want to have a separate dir for my routing.
Right now I have / served up by node.js like everything else but if I'm just testing my node.js server and I take it down, I'd like / to fallback to an nginx version of index.html. In this case, if my node.js server is taken down, then I get a 502 Bad Gateway.
I'm not too worried about performance from serving up files via nginx vs. node.js, I just figure that I want to have nginx handling basic pages if node.js goes down for whatever reason.
Relevant script:
location = / {
index index.html
root /path/to/public
try_files $uri $uri/ index.html;
}
location / {
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;
proxy_pass node_js;
}
If I use this above code, all requests still get sent to node.js, including /.

I think the simplest thing to do if it's just the index.html is to set index to
index index.html
root /path/to/public
All files in your public directory should now be served from nginx.
Now put this index.html in the public directory of your node app. The rest will be proxied from nginx to the node instance.
Of course you can simply put other static html in subdirectories if you want:
public/about(index.html
public/faq/index.html
...

Related

Nodejs Child Process on another server using server to server communication

I want to run the child process using node js from one server to another. I have a too heavy process to run that causing my main server to work slowly so I want to run my heavy processes on another server that will perform heavy tasks like data modifications and return a buffer of that data but I could not find similar like this.
For example, I have server A that is running my website and users are sharing their content using this. When the users' traffic jumps to high my server will get slow because of data like images, videos upload, and pdf report generating on the basic images, videos and serving the site content. I want to perform these tasks on server B, so that server A will only work for data serving and traffic management.
Apparently at this point you probably need to split your webserver frontend routes into different worker servers.
Let's suppose you're using Nginx as a website frontend. If you're not, then your first step would be to setup an nginx webfront.
1 - If haven't done so, serve all public static content (like pdf files, videos, images, etc.) directly from nginx using different rules for static content and node server routes:
Something as basic as this:
server {
listen 80;
server_name example.com;
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:5000;
}
location /static {
root /dir/to/my/static/files; # here you have your videos, images, etc.
}
}
2 - Now, if you need to separate your node server onto 2 services, you can just create 2 (or more) nginx proxy rules:
server {
listen 80;
server_name example.com;
location /api {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.2:5000; # server 2
}
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:5000; " server 1
}
location /static {
root /dir/to/my/static/files;
}
}
That way example.com/api/* routes will go to your secondary Node server (on ip 127.0.0.2), example.com/static will be served directly by Nginx at blazing fast speeds, while the non-mapped routes will be served by the default main node server on 127.0.0.1.
There are many ways to setup proxies and optimize Nginx so that it can, for instance, go through a pool of node servers in round-robin fashion, and you can also compress data and use protocols like HTTP/2 to take the load off the slower node-based webserver (ie. Express).

Nginx secure serve static file

im buildin a MEAN stack application, and i just found out that it's a best practice to let Nginx serve static file (Currently my node is serving static file) and use reverse proxy. so i was able to serve a static file and reverse proxy on Nginx, my question is, is there a way to secure the access to the static file?
This is my Nginx code
server {
listen 80;
location /static {
alias /var/www/project/public;
autoindex off;
}
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;
}
}
Under the public folder, i have style.css
so when i go to the url localhost/static/style.css, i could see my code, so i imagine lets say i deployed my website to the public and have it's domain name, the users could access my static files by just going to www.domainname.com/static/style.css
Is this normal? or there's a way to just limit the access to NodeJS server? being the only thing could access the static file? or im getting this wrong.
Thanks! sorry im new to this web development world, but im learning.
You can limit access using nginx by adding the following to your location definition:
#This would be the IP of the server you want to have access to your protected file
allow 123.123.123.123/32;
deny all;
But in this case, you don't want to restrict access to your static files. The user loading the web page needs access to the css files to display it correctly. If you were to watch the network traffic of when you loaded a web page, you would see that your browser downloads all the client side CSS, JS, and HTML files it needs to run properly. So it is completely normal for people to be able to just look at CSS files that are hosted statically. Usually a backend NodeJS server has no use for CSS files.

Node JS - Nginx - proxy_pass to a subdirectory - Koa

I'm running a Koa app on port 5000, and i'd like Ngnix to serve the app in a sub-directory - e.g: http://example.com/myNodeApp
Here's what I've currently got in /etc/nginx/sites-enabled/default
location ^~ /myNodeApp/ {
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;
proxy_pass http://localhost:5000/;
}
This kind of works... apart from the fact that any redirect e.g this.redirect('/') in my Koa app goes to the the nginx web root /
Also, it doesn't render anything from my Koa apps' public directory e.g. stylesheets, javascript and images.
What am I doing wrong? Thanks.
I have recently come across the same problem and here's what I did to fix it.
In Server Config:
I had to add
rewrite ^/myNodeApp/(.*)$ /$1 break;
to the NGINX config, in the
location /myNodeApp/ {...}
block, under what you already have in your example.
In client side:
I added
<base href='/myNodeApp/'>
to the <head> of my html files (or pug layout file in my case). This prefixes any links with your subdirectory.
Note that you will need to remove any leading /'s from your existing links. Eg
<link rel="stylesheet" href="layout.css">
instead of
<link rel="stylesheet" href="/layout.css">
That one caught me out for a while.
Bonus:
If you're using Socket.IO, like I am, you'll need to make a few more changes to stop some errors appearing in your console. You need to pass it a path option and specify your subdirectory.
In your html files
var socket = io.connect("/", {path: "/myNodeApp/socket.io"})

Which is most efficient : serving static files directly by nginx or by node via nginx reverse proxy?

I already use nginx as reverse proxy to serve my node.js webapps 3000<->80 for example. Actually, I serve my assets in the node app, using express.static middleware.
I read and read again that nginx is extremely efficient to serve static files.
The question is, what is the best ? Serving assets as I already do or configuring nginx to serve the static files itself directly ?
Or it is almost the same ?
The best way is to use nginx server to serve you static file and let you node.js server handle the dynamic content.
It is usually the most optimized solution to reduce the amount of requests on your node.js server that is slower to server static files than nginx for example :
The configuration to achieve that is very easy if you already set a reverse proxy for you nodejs app.
nd nginx configuration could be
root /home/myapp;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location /public/ {
alias /home/myapp/public/;
}
location / {
proxy_pass http://IPADRESSOFNODEJSSERVER:8080;
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;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
}
Every request with /public/ at the first part of the url will be handled by nginx and every other request will be proxied to you nodejs app at your IPADRESSOFNODEJSSERVER:NODEJSPORT usually the IPADRESSOFNODEJSSERVER is the localhost
The doc section of express tell that http://expressjs.com/en/advanced/best-practice-performance.html#proxy
An even better option is to use a reverse proxy to serve static files;
see Use a reverse proxy for more information.
Moreover nginx will let you easily define caching rules so for static assets that doesn't change it can speed up your app also with one line.
location /public/ {
expires 10d;
alias /home/myapp/public/;
}
You can find a lot of articles that compare the both methods on internet for example:
http://blog.modulus.io/supercharge-your-nodejs-applications-with-nginx

node.js angular jade client and node.js rest api

Are there any good examples or guidance anyone can provide for structuring an app like this?
Client (client.company.com)
Node.js
Angular
Jade
ExpressJS
Server (private) (server.company.com)
node.js
"rest" api (express)
The api is private right now, only accessible from the hosted servers.
If there is a page which creates recipes for example, is this right?
client
- angular form with router that posts to client.company.com/recipe
- express would need route to handle that /recipe
- that route would then post to api server server.company.com/recipe
- then response would be propagated through the layers back to the ui.
Is that right having the client duplicate the api routes? Is there anything that can be done to simplify and make things with less duplication?
angular forms should just post directly to the api server. Express is used just to serve the angular html/javascript/static files. The less layers in between the html and api the better. I don't see any good reasons why you need the client to duplicate the api routes.
Since your api is behind the hosted server, you can setup nginx server to routes all your api calls from the hosted server to the api server. The below is a sample nginx configuration to do the routing:
upstream clientServer {
server client.company.com:80;
}
upstream apiServer {
server server.company.com:80;
}
server {
location / {
root html;
index index.html index.htm;
proxy_pass http://clientServer;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /api {
proxy_pass http://apiServer;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Note the above is a snippet of the nginx.conf.
Nginx will look at your URL path.
requests accessing / path will go to client server (where you can host express js and angular files)
requests accessing /api/* path will be forwarded to the apiserver
Your angular form can then call the api directly to /api/*
Hope that helps.

Resources