Binding a Node.js App to Port 80 with Nginx

Sep 26, 2015

You've finished building your first Node.js web app, and boy, is it awesome. Everything works great on your development machine, but when you try to deploy to production, your app just won't bind to the desired port. This is because Linux restricts apps from binding to the first 1024 ports unless they are given root permissions, to prevent malicious processes from binding to sensitive ports such as 80, 443, 22, 21, etc.

Here are a few ways to deal with this security constraint:


IPTABLES

One way is to set up an iptables forwarding rule. iptables will then bind to the desired port (80 or 443) and forward all incoming traffic to your application's port, such as 1337.

However, this solution requires that you persist the iptables rule so that it gets executed on system startup, because your machine will crash or reboot eventually.

Redirecting traffic from one port to another

Let's issue the following command to redirect incoming traffic on port 80 to our Node.js app that is listening on port 1337:

sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 1337
Automatically re-apply the rule on system reboot

Next, go ahead and install iptables-persistent to save the rule permanently and have it reapplied automatically when your system reboots:

sudo apt-get install iptables-persistent
sudo /etc/init.d/iptables-persistent save 

That's it. Now your Node.js app is accessible on port 80 and you should be good to go.


NGINX

A more popular approach is to set up Nginx as a reverse proxy by having it bind to the desired port, forwarding all incoming traffic to your Node.js app.

Nginx is a high performance, open source web server (similar to Apache) that is widely-used as a reverse proxy for Node.js apps.

The main benefit of Nginx is the fact that it takes care of transport optimization. It sends cache headers for static resources and compresses them so that your Node.js app doesn't have to deal with that stuff. Focus on building your product, and let Nginx take care of optimizations.

Installing Nginx

Easy as pie.

sudo apt-get install nginx
Configuring Nginx

Next, we'll need to configure Nginx so that it forwards traffic to our app. Let's start off by removing the default configuration file:

sudo rm /etc/nginx/sites-enabled/default

Next, create a new file in /etc/nginx/sites-available/ called node and open it with nano:

sudo nano /etc/nginx/sites-available/node

Paste the following code in the file and make sure to change example.com to your domain (or IP), and 1337 to your Node.js application port:

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:1337";
    }
}

The proxy_pass declaration configures Nginx to act as a reverse proxy by forwarding all incoming requests on port 80 to your Node.js app on port 1337, on behalf of the client.

Next, we need to symlink our configuration to sites-enabled for it to be used by Nginx, since it's currently in sites-available:

sudo ln -s /etc/nginx/sites-available/node /etc/nginx/sites-enabled/node
Applying the Configuration

Let's restart Nginx so that it loads our configuration:

sudo service nginx restart

All set! Nginx will now forward all incoming requests to your app and even survive a server crash, since it automatically starts up with your machine.