Production Ready Node.js using Reverse Proxy

For many of the Node developers, node index.js  is the way to start the application server. While there is nothing wrong with it, it is not a recommended thing to do in the production environment. This article guides you on how to deploy production-ready Node.js using reverse proxy. But before all this, let me tell you how is node.js a language different from its ancestors.

Node.Js is one of the most popular technologies used for web development in the current generation. It arrived in 2012 when languages like PHP and ROR were ruling the market and made it’s way to the top. Before NodeJS, developers had to depend on other servers like Apache, Nginx, etc. But NodeJS is shipped with its server. That’s right you no longer need to install apache and go through clumsy php.ini configurations to set up your server. Just 2-3 lines of code and a simple command node index.js  and the server is up and running. It also allowed to serve files as they were uploaded and very easy handling of Web Sockets.

None can deny the fact that NodeJS is production-ready, however, almost every brain in the IT industry will recommend you not to expose the Node Js process directly to the web. One should always wrap the Node Js process inside reverse proxy and expose that proxy to the web.

This post will answer both the questions, Why and How! But before let us try to understand what reverse proxy server is, and before reverse proxy let us try to understand what proxy server is.

Proxy Server

Proxy Server is a normal server that sits in front of clients (set of computers trying to visit sites on the internet).  Whenever a client tries to access some website, the request first goes to the proxy server, it then hits the actual website the user wanted to hit. Please note the proxy server manipulates the request in such a way that to the destination website, the request seems to be coming from proxy. The website is unaware of the original client who initiated the request. It just knows about the proxy server and responds to the proxy server. The proxy server upon receiving the response delegates it to the client who initiated the request.
Thus we see that the proxy server acts as a middleman. The advantages of disadvantages of a proxy server are beyond the scope of this article and will be dealt with separately.

 

 

Reverse Proxy Server

A reverse proxy sits in front of servers (one or more) and intercepts the requests coming from clients. Suppose we have a website A with many servers, all behind a reverse proxy server.
When a client hits the website A, the request first goes to the reverse proxy server which then delegates it to the server. Again manipulation happens and to the actual website server, the request seems to be coming from the reverse proxy server. The website server responds to the reverse proxy server. The reverse proxy server then delegates the response to the client.

There is a minute but subtle difference between a Proxy and Reverse proxy server. A proxy server makes sure no client directly hits the website server. A reverse proxy makes sure no web server is directly accessed by a client.

 

Reverse Proxy | Credits: excitingip.com

Why reverse proxy in production?

As already stated,  one should always wrap node.js process in reverse proxy and then expose the reverse proxy to the internet. Let us see the reasons behind this.

  • SSL Termination:   SSL stands for Secure Sockets Layer. It is a necessary security protocol in modern-day internet. Again going into a deep explanation of SSL is beyond the scope of this article, however, it is safe to understand that SSL deals with public/private certificates and involves a lot of encryption/ decryption of request/response. Node js is completely capable of all these operations, but it is not desirable to choke the process with these operations. Not only does it increases the burden on the web app but it also compromises with the security as the certificates are exposed in the runtime.
    Therefore it is better to terminate SSL outside the web app, in the reverse proxy. To make things clearer, the client hits the reverse proxy server with SSL encrypted request using HTTPS protocol. Reverse Proxy servers terminate the SSL (decrypts the SSL encrypted request) and send the decrypted request to the web app using the HTTP protocol, thus saving the overhead on the web app to decrypt the payload. Reverse happens while sending the response.  Using tools like certbot and Let’Encrypt makes this task very easy. I have done this for a personal project of mine and will share it in the next article.
             SSL Termination | Credits: avinenetworks.com

 

  • Compression:    Compression is one more advantage of using Reverse Proxy. Big Asset files can be compressed at the reverse proxy server and thus the main web app never faces large chunks of binary data. The rules for compression are also set at the Reverse Proxy Server level and thus remain constant for all the web app servers.
  • Caching:     Just like a forward proxy, data can also be cached in reverse proxy servers.  Thus the server saves time in serving a request increasing the overall performance of the web app.

There are many other advantages of reverse proxy like an established proxy server is easier to manage, logs are better handled, etc. In the next part, we shall see how to wrap a node js process inside the reverse proxy.

 

How to implement reverse proxy?

In this section, we will be implementing reverse proxy wrapping a node js process within the apache reverse proxy server.  This section really answers how to make production-ready node.js using reverse proxy. We shall be using pm2 the process management tool to fire node js server. This post has been written for Ubuntu 18.04 environment, however, everything other than the installation steps are the same for any environment.

Let us go step by step.  I assume we already have a web app in a folder named nodejsApp  running on port 3000 with index.js as the entry point. I also assume the domain of the website to be www.abc.com and we want all the requests coming to port 80 on www.abc.com/nodejsApp to be delegated to node js process running on port 3000.

    • install apache2 and pm2.
      sudo apt-install apache2
      npm install -g pm2
      
    • Run the node js app using pm2.
      cd nodejsApp
      pm2 start index.js
    • To achieve routing the requests coming to www.abc.com/nodejsApp port 80 to node js process on port 3000 we need to enable mod_proxy and mod_proxy_http modules on apache server.
      a2enmod proxy
      a2enmod proxy_http
    • Next, it is time to edit a virtual host of the apache server. If you are new to apache or have made no virtual hosts as of now, just edit the 000-default.conf.
      vim /etc/apache2/sites-available/000-default.conf
    • Add the following content to the file.
      <VirtualHost *:80>
      # The ServerName directive sets the request scheme, hostname and port that
      # the server uses to identify itself. This is used when creating
      # redirection URLs. In the context of virtual hosts, the ServerName
      # specifies what hostname must appear in the request's Host: header to
      # match this virtual host. For the default virtual host (this file) this
      # value is not decisive as it is used as a last resort host regardless.
      # However, you must set it for any further virtual host explicitly.
      ServerName www.abc.com
      
      ServerAdmin webmaster@localhost
      DocumentRoot /var/www/html
      
      <Directory />
      Options -Indexes +FollowSymLinks
      AllowOverride None
      Require all granted
      </Directory>
      ProxyRequests Off
      ProxyPreserveHost On
      ProxyVia Full
      <Proxy *>
      Require all granted
      </Proxy>
      
      <Location /nodejsApp>
      ProxyPass http://127.0.0.1:3000
      ProxyPassReverse http://127.0.0.1:3000
      </Location>
      
      # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
      # error, crit, alert, emerg.
      # It is also possible to configure the loglevel for particular
      # modules, e.g.
      #LogLevel info ssl:warn
      
      ErrorLog ${APACHE_LOG_DIR}/error.log
      CustomLog ${APACHE_LOG_DIR}/access.log combined
      
      # For most configuration files from conf-available/, which are
      # enabled or disabled at a global level, it is possible to
      # include a line for only one particular virtual host. For example the
      # following line enables the CGI configuration for this host only
      # after it has been globally disabled with "a2disconf".
      #Include conf-available/serve-cgi-bin.conf
      </VirtualHost>
      
      

      In this file, we have added a reverse proxy for path /nodejsApp and redirected it to localhost:3000 (as the node js process is running on the same server).

    • After this, we only need to enable the virtual host in which we have placed the code and restart apache2. As we have placed the code in 000-default.conf, we need to enable it, we can just restart apache2.
      service apache2 restart

 

And this is it. You now have a node js web app running behind a reverse proxy server on Ubuntu 18.04. We can configure multiple URLs, in the same way, creating different virtual hosts and enabling the required ones. And thus you make production-ready node.js using reverse proxy.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

error

Enjoy this blog? Please spread the word :)