By Robotbugs


2013-05-15 19:42:41 8 Comments

I am setting up my first Node.js server on a cloud Linux node and I am fairly new to the details of Linux admin. (BTW I am not trying to use Apache at the same time.)

Everything is installed correctly, but I found that unless I use the root login, I am not able to listen on port 80 with node. However I would rather not run it as root for security reason.

What is the best practice to:

  1. Set good permissions / user for node so that it is secure / sandboxed?
  2. Allow port 80 to be used within these constraints.
  3. Start up node and run it automatically.
  4. Handle log information sent to console.
  5. Any other general maintenance and security concerns.

Should I be forwarding port 80 traffic to a different listening port?

Thanks

4 comments

@Meet Mehta 2014-04-24 23:03:19

Give Safe User Permission To Use Port 80

Remember, we do NOT want to run your applications as the root user, but there is a hitch: your safe user does not have permission to use the default HTTP port (80). You goal is to be able to publish a website that visitors can use by navigating to an easy to use URL like http://ip:port/

Unfortunately, unless you sign on as root, you’ll normally have to use a URL like http://ip:port - where port number > 1024.

A lot of people get stuck here, but the solution is easy. There a few options but this is the one I like. Type the following commands:

sudo apt-get install libcap2-bin
sudo setcap cap_net_bind_service=+ep `readlink -f \`which node\``

Now, when you tell a Node application that you want it to run on port 80, it will not complain.

Check this reference link

@Kyle Chadha 2015-01-06 18:35:36

This is the better, simpler answer.

@Meet Mehta 2015-07-06 20:37:26

Also, added detailed answer here stackoverflow.com/questions/23281895/…

@Luca Steeb 2015-07-27 20:03:09

Best answer. :)

@Eric Andrew Lewis 2016-04-08 18:32:55

How does a web server like NGINX run on port 80? Does it do something similar?

@Meet Mehta 2016-04-08 20:04:50

@EricAndrewLewis: I will say it depends. This error will show up when you are running the server in non-root mode. What if you are running the Nginx server as root user! Also, if running as normal user and getting error. Run above commands to give safe permissions to access the port. Also refer to stackoverflow.com/questions/31369480/…

@slund 2016-06-22 19:28:22

Drop root privileges after you bind to port 80 (or 443).

This allows port 80/443 to remain protected, while still preventing you from serving requests as root:

function drop_root() {
    process.setgid('nobody');
    process.setuid('nobody');
}

A full working example using the above function:

var process = require('process');
var http = require('http');
var server = http.createServer(function(req, res) {
    res.write("Success!");
    res.end();
});

server.listen(80, null, null, function() {
    console.log('User ID:',process.getuid()+', Group ID:',process.getgid());
    drop_root();
    console.log('User ID:',process.getuid()+', Group ID:',process.getgid());
});

See more details at this full reference.

@Daniel 2013-05-15 19:47:24

Port 80

What I do on my cloud instances is I redirect port 80 to port 3000 with this command:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

Then I launch my Node.js on port 3000. Requests to port 80 will get mapped to port 3000.

You should also edit your /etc/rc.local file and add that line minus the sudo. That will add the redirect when the machine boots up. You don't need sudo in /etc/rc.local because the commands there are run as root when the system boots.

Logs

Use the forever module to launch your Node.js with. It will make sure that it restarts if it ever crashes and it will redirect console logs to a file.

Launch on Boot

Add your Node.js start script to the file you edited for port redirection, /etc/rc.local. That will run your Node.js launch script when the system starts.

Digital Ocean & other VPS

This not only applies to Linode, but Digital Ocean, AWS EC2 and other VPS providers as well. However, on RedHat based systems /etc/rc.local is /ect/rc.d/local.

@Robotbugs 2013-05-15 21:49:53

Thanks for that answer, nice and to the point.

@kehers 2013-10-14 07:14:31

BTW, on Ubuntu, it is /etc/rc.local

@Victor 2014-01-25 18:23:26

You are awesome, works like a charm.

@JHAWN 2014-04-07 02:15:05

Often the "-i eth0" flag will be an issue for virtual private servers. Replace eth0 as needed.

@jamix 2014-06-11 12:44:31

If I add my Node.js start script to /etc/rc.local, won't it be executed as root on system boot? That would defeat the purpose of the port 80 redirect.

@Daniel 2014-06-12 17:32:06

Yes, this is true. If you start your node.js script from /etc/rc.local it will run as root. However, security best practices are to never run a server as root.

@moderns 2014-07-18 12:45:35

But I run webserver on port 80, so the webserver wont work in this case. Please advise.

@Daniel 2014-07-19 19:34:05

If you have a web server already running on port 80 then you'll need to configure it to be a reverse proxy for the Node.js backend server.

@dgallant 2014-07-22 01:56:27

This works but not alongside my VPN (which I host on the same VPS).

@Sprout Coder 2014-10-08 15:01:19

What do you mean by add Node.js script to /etc/rc.local ? Do I simply need to add a line that calls the script, i.e. line : node server.js ?

@bk138 2014-12-06 22:28:12

Note that for the port redirect to work, the destination port needs to be opne on your firewall as well. WRT starting a node instance on boot, we simply make use of the distributions's init scripts/systemd files that allow you to specify a user.

@JCM 2015-02-09 20:07:20

Let's say that I have two ip available, one which is bound to apache on port 80, how would I add the other one to the command above?

@Daniel 2015-02-10 18:14:41

@JCM you would change -i eth0 to -i eth1. That would target the second interface instead of the first interface.

@JCM 2015-02-10 20:05:27

@Daniel what if the ip is inside a sub interface (eth0:cp1)?

@Daniel 2015-02-12 19:48:27

@JCM I haven't actually used it with a sub interface, but I suspect it would work the same way.

@ndmweb 2015-04-30 22:28:13

@jamix & OP: Is there a solve for the rc.local command running as root?

@jamix 2015-05-01 07:04:35

@ndmweb Before we switched our Node.js app to Elastic Beanstalk where this is taken care of for us, we used process.setgid() and process.setuid() in the app itself to downgrade its permissions to those of a specially created nodejs system user.

@Sahan 2015-05-02 02:17:16

@Daniel, The sockets sent to :80 does not seems to get forwarded to :3000 ? Can you help please ?

@Arthur Collé 2015-06-25 02:52:29

Thanks! -from the Phoenix/Elixir world

@MFARID 2015-10-07 14:42:57

Make sure you get the -i correct, or remove it

@Sudhanshu Gaur 2016-03-04 19:45:12

what do you mean by add Node.js script to /etc/rc.local can you please tell me what should i wriye and also i i am using forever also ??

@vol7ron 2016-03-13 19:51:52

@Daniel when rerouting, does ufw also need to allow the specificed port? Given your example, I've noticed this only works when 3000 is allowed via the firewall (ufw allow 3000/tcp), but that also allows anyone to access via that port; so an external person could get to the page by domainname.com (defaults to 80), domainname.com:80, domainname.com:3000, and ip address (e.g, 123.456.789.012:80/3000). I thought the desire was to allow TCP traffic on 80 to be served internally by port 3000; so all ports closed to external users except 80.

@vol7ron 2016-03-13 19:59:26

@bk138 I think I just repeated what you previously stated -- is that correct? Is it possible to do port forwarding internally?

@Naveen Attri 2016-10-24 21:41:47

If I use this solution and later I want to remove this redirection of traffic, then how to do it?

@Pedro Emilio Borrego Rached 2016-12-03 12:23:01

fantastic, seccond line of the solution worked like a charm on one of my servers. Thanks!

@Atomox 2017-03-08 22:24:37

Instead of adding the iptables changes to rc.local, how about editing /etc/network/interfaces, adding these two lines: pre-up iptables-restore < /etc/iptables.rules post-down iptables-save > /etc/iptables.rules

@Marius 2017-05-08 19:54:43

On a wireless laptop, can one leave out "-i eth0"? I tried this, but still doesn't work: iptables -F iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 5000

@tonejac 2017-06-14 06:10:11

Rock on! That was perfect! Works like a charm!

@Shreyas 2017-07-20 04:36:32

how do i undo this command?

@Nulik 2017-10-25 00:30:52

very bad solution, you are loading your kernel with unnecessary traffic. all the packets are copied from one buffer to another, you are wasting resources. much better option is to setuid 0 to node process at the initialization so it can acquire privileged port, after bind() you just drop privileges.

@zed 2018-10-11 11:59:58

If you are on AWS and using the ELB, just forward the ELB ports to the correct instance ports. This solution wouldn't work if you have multiple applications running on different ports.

@divillysausages 2019-05-03 09:26:00

Small point, on at least AWS: in the /etc/rc.local file there's the line Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure that this script will be executed during boot. I had the line in, but hadn't run the chmod command and it didn't update when the machine was relaunched

@Nick Benes 2014-01-24 13:08:47

For port 80 (which was the original question), Daniel is exactly right. I recently moved to https and had to switch from iptables to a light nginx proxy managing the SSL certs. I found a useful answer along with a gist by gabrielhpugliese on how to handle that. Basically I

Hopefully that can save someone else some headaches. I'm sure there's a pure-node way of doing this, but nginx was quick and it worked.

Related Questions

Sponsored Content

22 Answered Questions

[SOLVED] How to kill a process running on particular port in Linux?

1 Answered Questions

How to configure port for Node.js Application in Cpanel?

10 Answered Questions

[SOLVED] Node.js Best Practice Exception Handling

14 Answered Questions

[SOLVED] How to run Node.js as a background process and never die?

17 Answered Questions

[SOLVED] How to decide when to use Node.js?

3 Answered Questions

[SOLVED] How to run node.js as non-root user?

1 Answered Questions

1 Answered Questions

[SOLVED] Why is running node.js on port 80 might not be safe?

  • 2013-10-16 17:21:04
  • soyuka
  • 2350 View
  • 1 Score
  • 1 Answer
  • Tags:   linux node.js

1 Answered Questions

[SOLVED] What ports should I node.js listen on? How and why?

Sponsored Content