One of the things that really got me on board with NodeJS was the idea that I didn’t need a host container for it. Building a web app just means including a library that listens for HTTP requests on a port and respond. No more Apache! One less thing to worry about that isn’t my app!

And then it starts getting complicated.

For a start, port 80 is a privileged port, so when you try to launch the app to test or develop on your own machine you need to do so with sudo. That’s a little annoying, but you could default to port 80 & allow an override. But now you are adding more code to workaround it.

And what about SSL? If you are going to use SSL in production (and you should) then your code is going to have to know about that too and read the certs and set that up. And that’s even more annoying for development, anyone working on your code is going to have to create their own certs just to launch your app. Unless you code in more workarounds.

So that’s a suddenly a lot of code you are maintaining which might create its own problems.

The alternative … use a webserver as a proxy for your app in production. It doesn’t have to be Apache, you could use Nginx for example. I use Apache because I’m reasonably familiar with it.

So what do you do?

  1. Just code your app without any of the SSL stuff, and let it listen on a non-priveleged port. Eg. 9000. This is easy and simple to work on in development.

  2. For production, deploy your app as is, let it just run on which ever port it wants. You probably want to block that port in your firewall config though.

  3. Then install Apache on your server and create a new virtual host. Configure this as a proxy to your app running on it’s own port. If you need SSL, set this up in the virtual host config too. This virtual host should be listening on port 80 or 443. If you are using SSL I’d suggest two virtual hosts: the port 443 one for SSL that is the proxy for your app, and a port 80 one to redirect to the SSL one.

This is an sample of Apache virtual host config that I use for this kind of setup. One virtual host listens on port 80 and redirects all requests to the https URL and a second virtual host listens on 443 and proxies those to the app on port 9000.

<VirtualHost *:80>
   ServerName appname.intranet.company.com
   Redirect permanent / https://appname.intranet.company.com/
</VirtualHost>


<VirtualHost appname.intranet.company.com:443>

  ServerName appname.intranet.company.com

    <Proxy *>
      Order deny,allow
      Allow from all
    </Proxy>

    #SSL Stuff
    SSLEngine On
    SSLProxyEngine On
    SSLCertificateFile /opt/secrets/appname/appname.crt
    SSLCertificateKeyFile /opt/secrets/appname/appname.key

    ProxyPreserveHost On
    ProxyRequests off
    ProxyPass / http://appname.intranet.company.com:9000/
    ProxyPassReverse / http://appname.intranet.company.com:9000/

</VirtualHost>

So in this model, your app doesn’t really know anything about how it will be deployed. It just knows that it’s listening on a HTTP port. This makes it easy in development because there is nothing additional to setup. In production however, the users won’t actually interact directly with it. Users will actually be interacting with an Apache virtual host that simply passes the requests along after it has provided some extra value of it’s own - value that isn’t required in development.