Node/Express best practice regarding multiple apps on 1 instance

301 views
Skip to first unread message

Aaron Martone

unread,
Sep 8, 2015, 2:11:42 PM9/8/15
to nodejs
Relatively new to Node, so if I make a statement that is outright wrong, please let me know.

Let's say I have 3 Express apps over 2 domains:

Default website: www.domain.com (/hosts/www/app.js)
Alpha API website: api.domain.com/alpha (/hosts/api/alpha/app.js)
Beta API website: api.domain.com/beta (/hosts/api/beta/app.js)

I'm looking to build an infrastructure that allows me to handle routing all incoming requests through a central "AppRouter" that looks at the Protocol, Domain and Port combination (what I'm calling an 'endpoint') to know which app to route the request off to. For example, if it sees:


it'll know that: "With protocol 'https' and domain 'www.domain.com' and port: 80, I send this to the 'Default website' express app (which takes over from that point to process the '/this/that' or remainder of the path in the url.

My problem I'm encountering, is that in order to bring up a 'AppRouter' application, I have to specify a port to bind to. So if I bind it to port 80, I'll miss all requests on https (443) or other ports I might want to support.

Am I taking the wrong approach to this functionality, or am I too complex in my approach? Does node support a more simplified approach to this problem like "Just spin up a node instance per app", etc.  I'm using a VPS hosting, and am new to it as well, so I appreciate any feedback from someone whose been in a similar situation.

Ryan Schmidt

unread,
Sep 8, 2015, 8:00:44 PM9/8/15
to nod...@googlegroups.com

On Sep 8, 2015, at 1:08 PM, Aaron Martone wrote:

> I'm looking to build an infrastructure that allows me to handle routing all incoming requests through a central "AppRouter" that looks at the Protocol, Domain and Port combination (what I'm calling an 'endpoint') to know which app to route the request off to. For example, if it sees:
>
> https://www.domain.com/this/that,
>
> it'll know that: "With protocol 'https' and domain 'www.domain.com' and port: 80, I send this to the 'Default website' express app (which takes over from that point to process the '/this/that' or remainder of the path in the url.
>
> My problem I'm encountering, is that in order to bring up a 'AppRouter' application, I have to specify a port to bind to. So if I bind it to port 80, I'll miss all requests on https (443) or other ports I might want to support.

An express app can be made to listen on multiple ports. You can listen both on port 80 and on port 443.

Alternately, your node app could listen on a single http port, and you could use another server in front of it (like nginx) that listens on both ports 80 and 443 and proxies requests on either port to your node app.

You may even find that a server like nginx in front of your "real" node apps already fits your needs and you don't need to write a separate "AppRouter".

Aaron Martone

unread,
Sep 8, 2015, 10:37:00 PM9/8/15
to nodejs
I've heard of NGINX, but have no experience with it. Since it's an additional server, I can only assume that it would be an additional expense to get up and running with my VPS, so let me see if I can find a solution at no additional expense before I go down that road.

I noticed that Node uses a 'http' and 'https' module for its respective .createServer() method. Is it wise to run multiple apps off 1 Node process? Or do most VPS (using Digital Ocean) allow you to spin up multiple Node processes, each independent from another?

Using the aforementioned apps, if I ran:

> node /hosts/www/app.js
> node /hosts/api/alpha/app.js
> node /nosts/api/beta/app.js

in 3 separate terminal processes?

Correct me if I'm wrong, but I think someone said that I must have a unique endpoint per application. The PROTOCOL + DOMAIN + PORT = the endpoint. So if all these apps were running on, say 443 (PORT) and HTTPS (PROTOCOL), then I'd have to have a unique DOMAIN. That's fine for the www.domain.com app, but the 2 apps on api.domain.com that just have different starting paths (api.domain.com/alpha and api.domain.com/beta) probably can't be done that way. I'd have to have an Express app per the 'https://api.domain.com:443' endpoint, and then it would have to read the url path and internally load the 'alpha' or 'beta' apps. And that's not too much of a problem if I'm right in all my assumptions. :)

Ryan Schmidt

unread,
Sep 9, 2015, 12:36:03 AM9/9/15
to nod...@googlegroups.com

On Sep 8, 2015, at 8:20 PM, Aaron Martone wrote:

> I've heard of NGINX, but have no experience with it. Since it's an additional server, I can only assume that it would be an additional expense to get up and running with my VPS, so let me see if I can find a solution at no additional expense before I go down that road.

If by "expense" you mean monetary, you'll have to ask your VPS provider. I thought the point of a Virtual Private Server was that you can run whatever programs you want on it; I didn't think they would charge you by the program.

If you mean CPU or memory expense, then I don't know. If you're writing a program to do the subset of nginx's functionality that you want, it's possible your custom program will use less CPU or memory than nginx. On the other hand, nginx has been in development for years and is probably highly optimized.

The expense (in terms of time and effort) of writing your own code to do what nginx already does would probably be greater than spending a little time with the nginx documentation to see how to use it.

Again I'm not sure if I understood your goals correctly, and it might be that you want to do something that nginx can't do. But if you don't know nginx yet, you probably owe it to yourself to investigate it first. Maybe using it can save you some time, if not for this specific task then maybe for something else later.


> I noticed that Node uses a 'http' and 'https' module for its respective .createServer() method. Is it wise to run multiple apps off 1 Node process? Or do most VPS (using Digital Ocean) allow you to spin up multiple Node processes, each independent from another?

From an organizational perspective, you probably want a separate process running each app. If they were really meant to run together, why would you make them separate apps in the first place?


> Using the aforementioned apps, if I ran:
>
> > node /hosts/www/app.js
> > node /hosts/api/alpha/app.js
> > node /nosts/api/beta/app.js
>
> in 3 separate terminal processes?

Running (multiple) apps from (multiple) terminals is great for testing. For production use, of course, you'll want something more robust, that doesn't rely on a terminal, and that automatically restarts processes in case of failure. Each OS has its own way of handling that, so consult your VPS operating system's documentation for how to do it on your VPS.


> Correct me if I'm wrong, but I think someone said that I must have a unique endpoint per application. The PROTOCOL + DOMAIN + PORT = the endpoint. So if all these apps were running on, say 443 (PORT) and HTTPS (PROTOCOL), then I'd have to have a unique DOMAIN. That's fine for the www.domain.com app, but the 2 apps on api.domain.com that just have different starting paths (api.domain.com/alpha and api.domain.com/beta) probably can't be done that way. I'd have to have an Express app per the 'https://api.domain.com:443' endpoint, and then it would have to read the url path and internally load the 'alpha' or 'beta' apps. And that's not too much of a problem if I'm right in all my assumptions. :)

Sure, each app that wants to listen on a port/IP must listen on a different port/IP. That's why usually people run nginx on the public port/IP (for example port 80 and/or 443 on your public IP), and run as many node apps as needed on private ports (port 3000, 3001, etc. on localhost or other private IP) and configure nginx to pass the appropriate requests to the appropriate app, based on the hostname or path or whatever.


Aaron Martone

unread,
Sep 9, 2015, 12:02:41 PM9/9/15
to nodejs
Thanks for the info, Ryan.

So it seems NGINX is a web/proxy/mail server (modularly supporting each) that can act as the front side face of my applications, to which it can URL rewrite, if need be, before routing off the requests to an individual Node App.  That sounds perfectly like what I'm looking for. I misinterpreted how NGINX worked, and confirmed with my host "You're free to install NGINX on your instance, just understand that in addition to all Node memory usage, NGINX will take up its share as well.) (I'm running a personal site on a 1GB VPS, but I'm sure I can scale if I ever need to)

And for clarification, what you're saying about the Node/App side of things, can you throw me a hint or 2 about some tech used for more automated assurances to run my apps? Are we talking about things like Forever, or services that work to constantly ensure that if the Node process dies, it is spun back up without my need to manually do it?

My apologies, the world of VPS is actually new to me, but I've been finding it VERY amazing and interesting in architecting reliability into the design of the application's infrastructure. I really appreciate you taking the time.

Zlatko

unread,
Sep 9, 2015, 1:27:07 PM9/9/15
to nodejs
You're asking for best practices: nginx is it. Put nginx in front, and it will even be faster and better then node at ssl stuff, so your app only listens on one port.

It is trivial to install, and it is simple to configure, read a little about node and nginx and multiple apps.
DigitalOcean 1GB droplet it's perfectly capable of housing nginx, a few small node apps, and maybe a small database, though it varies, depends on usage.

As for terminals, either look into forever or pm2 modules oh npm. They each have good docs on how to do the setup you want.

Aaron Martone

unread,
Sep 9, 2015, 2:47:24 PM9/9/15
to nodejs
Thanks Zlatko!

I've installed Ubuntu 14.04 via Virtualbox (on Win7 Pro x64), gave it 100GB of space and 1GB of RAM and 2 cores of my CPU so I could have a similar local environment. I'm definitely not looking to running large apps. Most just some API frameworks, testing and a personal website. But it's good to know my infrastructure can scale to my needs through my host. So I'm glad to hear that a droplet should be able to run those things. I guess you guys have confirmed my course, so now all I need to do is setup my

And before you ask, I'm using Win7Prox64 because I'm a gamer (sorry Linux/OSX, I wish it were true for you so I could fully ditch Windows), but I don't want to dual boot over to Linux so Virtualbox was the next best thing (Bring it up when I want to code, close it to play some games). I think I can even setup shared files between them so I don't have to worry about installing Sublime Text 3 on it and can code on 1 window of my setup (Windows/Sublime), save it (saves in a shared location), and then test it on the Ubuntu environment.

Man, virtualized environments are schnazzy. :)

I just gotta resolve this issue where the Ubuntu/VirtualBox resolution shows as being really low now...

Robert Zehnder

unread,
Sep 10, 2015, 9:56:21 AM9/10/15
to nodejs
Maybe a silly question, but did you install the guest additions in virtualbox? 

Tom Boutell

unread,
Sep 10, 2015, 10:11:47 AM9/10/15
to nodejs
We wrote a CLI to automate nginx configuration as a reverse proxy for one or more node apps on a VPS, which is your exact use case. Check it out:

Aaron Martone

unread,
Sep 10, 2015, 12:55:17 PM9/10/15
to nodejs
@Robert Zehnder
I believe I did. I've got Ubuntu to a point where it "says" the desktop is what my Host machine's resolution is (2560x1440) but in actuality, I think it's forced to a 4:3 aspect ratio and is about 1280x1024. Enough for my needs,but I noticed an odd graphical issue where upon boot of the guest OS, the screen is corrupt. Luckily, I found an article where someone said if I press RCTRL + F1 and then RCTRL + F7, it actually restores the desktop of Ubuntu visually and from there on out, everything works just fine.

As a sad note, it seems my share that I set up yesterday is gone. So, I'm taking some PluralSight training courses on learning the Linux CLI, but til then I'll see if I can't setup a share on my Windows Host and then get VB to see it as a shared location for my Ubuntu host. That way I can code in Windows, an execute on what will be my production environment through VB, in Ubuntu.

@Tom Boutell
Very shack! I'll take a look at that package and see if I can put it to good use. Thanks!

Ryan Schmidt

unread,
Sep 14, 2015, 1:11:05 AM9/14/15
to nod...@googlegroups.com

On Sep 9, 2015, at 8:53 AM, Aaron Martone wrote:

> And for clarification, what you're saying about the Node/App side of things, can you throw me a hint or 2 about some tech used for more automated assurances to run my apps? Are we talking about things like Forever, or services that work to constantly ensure that if the Node process dies, it is spun back up without my need to manually do it?

If you're just testing a node app, you can start it on the command line, no problem.

If you want that app to run a production web site, you'll want to take care of two things:

1. starting your node app when the your boots (even if you don't plan to reboot your vps ever, it might reboot for reasons outside of your control, including the whims of your hosting provider and unexpected power loss)

2. restarting your node app if it quits (most node apps are designed to quit when they encounter an unexpected situation, and also your app might crash)

On OS X, launchd would handle both of those things, if asked to do so via a config file (plist) that you would write. On Linux variants that use systemd, it would handle both, again if so configured. AFAIK the majority of Linux variants do not use systemd, so you may need to handle these two things separately, using whatever facilities are built into your flavor of Linux, or using other tools. I don't use Linux so I can't guide you specifically.

Aaron Martone

unread,
Sep 14, 2015, 11:31:49 AM9/14/15
to nod...@googlegroups.com
Interesting. I'd love to pick your brain about best practices with ensuring delivery of my NGINX and Node Apps.

My production environment is running Ubuntu 14.04, and my local development environment is running Ubuntu 14.04 emulated on VirtualBox on a Windows 7 Pro x64 host machine. 

Recently I learned how to parse command line arguments given to the node process so that I can indicate to my node app whether I want to run it in a set environment (development/staging/production) or to let it look for the NODE_ENV local environment variable, or default to development if not specified. But ensuring that NGINX and the Node apps auto run on server start; I never even gave that much thought!

I've recently downloaded PM2 and am reading up on documentation for it to ensure that specified Node apps are run when the server starts. It also ensures that if the apps crash, they are restarted (go availability!). But as for NGINX. My OSX laptop is mostly for development when I'm out of the house. Otherwise I'm developing "through" Windows on Ubuntu (I gave my virtual machine 2 of 6 cores, 4 of 16GB RAM and 100GB of 500GB as far as resources go, so it more than emulates my hosts's 2-core, 1GB, 30GB instance. But if you have information on how to setup NGINX to auto-start on server boot, I'd love to hear that.



--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to a topic in the Google Groups "nodejs" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nodejs/8yH6BbvHBrw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/A1310D89-008C-4E95-A1E6-07996A3734EC%40ryandesign.com.
For more options, visit https://groups.google.com/d/optout.

Aaron Martone

unread,
Sep 14, 2015, 12:56:09 PM9/14/15
to nod...@googlegroups.com
This brings up a tricky situation.

==> I develop my apps on my Host Windows 7 Pro x64 environment, using Sublime Text 3 primarily.
==> This host has a share: "dev" located at c:\dev
==> In that share, I have a folder 'web-root', which contains a folder for each website I'm working on, so let's just say there's 1 in there called "domain.com"
==> Also in c:\dev is a folder 'web-server', which I created a series of subfolders for: 'c:\dev\web-server\nginx\conf\', here I put all the config files that comes with NGINX (including the nginx.conf file)
==> The whole c:\dev is shared with my VM Ubuntu (which is located at /media/sf_dev. I similarity sake, I created a symlink in my home directory called 'dev' which pointed to /media/sf_dev, and sure enough, I can see the 'web-root' and 'web-server' folders that are actually on my host machine.
==> I need to figure out how to tell NGINX, which auto-boots on Ubuntu to use the nginx.conf which is located at /media/sf_dev/web-server/nginx/conf/nginx.conf (or /home/aaron/dev/web-server/nginx/conf/nginx.conf)
==> I do this because from Windows I want to be able to configure all relevant files I need to in order to configure the guest (Ubuntu) environment from my Host (where my editor is). I just want to use the guest environment for emulating being a web server.

I found out that I had to modify my virtual machine's network adapter to act as a bridge so that I can test my web server (NGINX on Ubuntu) from my host machine. I gave it a static 10.x.x.x address, changed the network adapter from 'host-only/NAT' to 'bridged' and now from my Windows PC, with NGINX up, I can modify my hosts file so that, say 'domain.local' goes to the 10.x.x.x address, and sure enough, the page is served (of course, this stopped working once I moved the .conf file, but I'm sure I'll be able to specify a different config folder location somehow.

Whew! And that's how I'm setup. Hopefully I made sense, but I thought you should get a big picture view.

Ryan Graham

unread,
Sep 14, 2015, 12:56:24 PM9/14/15
to nod...@googlegroups.com

The Ubuntu package for nginx would have set it to start automatically, if I recall correctly. I don't recall off the top of my head if it uses sysv init scripts or Upstart, though.

Since you are on Digital Ocean, you may have noticed that they offer credits for users who write how-to guides. As a result, there are actually a large number of step by step guides specifically for what you are doing. There is literally a guide for setting up node + nginx on Ubuntu 14.04. Please don't take that as an RTFM, more as a reference to a source of information that doesn't involve waiting for a someone to reply and that reply to go through moderation ;-)

I'm not sure how familiar you are with shell scripting, so this may or may not be obvious to you. If you keep notes on what commands you run in your local VM so that you can copy/paste them into your remote VM, there are  decent odds that the file you are storing those notes in could be run directly as a shell script instead of one line at a time.

~Ryan


You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.

To post to this group, send email to nod...@googlegroups.com.

Aaron Martone

unread,
Sep 15, 2015, 10:53:38 AM9/15/15
to nod...@googlegroups.com
Thanks Graham. Sadly, not too familiar with shell scripting (but I am getting into it, and can see how powerful it is) Right now, since I'm so new to Ubuntu, just learning the filesystem is a bit disorientating at first; but slowly I am finding articles and resources that are clarifying. It's true that an OS like this is really a configuration that loads a configuration which loads a configuration, lol. As confusing as that can be to someone new, I do know that it also leverages a level of customization that is probably one of the main reasons people herald the OS in the first place.

So far, I've custom installed NGINX, Node/NPM and Mongo via apt-get; I have my Node apps running automatically via PM2, and now just have to find a resource to find how Ubuntu loads NGINX, so I can pass it the -c switch along with the path to my new .nginx.conf.

But as I'm sure we all here know, this field is a never-ending battle of learning new skills. That sense of challenge (and triumph once you figure it out) is rewarding on the pro side, but very time consuming on the con, lol. Thanks to all for the push in the right direction!

Reply all
Reply to author
Forward
0 new messages