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:
- Set good permissions / user for node so that it is secure / sandboxed?
- Allow port 80 to be used within these constraints.
- Start up node and run it automatically.
- Handle log information sent to console.
- Any other general maintenance and security concerns.
Should I be forwarding port 80 traffic to a different listening port?
Thanks
Related Questions
Sponsored Content
22 Answered Questions
[SOLVED] How to kill a process running on particular port in Linux?
- 2012-07-20 16:39:17
- veer7
- 1005312 View
- 642 Score
- 22 Answer
- Tags: linux unix port kill-process
1 Answered Questions
10 Answered Questions
[SOLVED] Node.js Best Practice Exception Handling
- 2011-09-05 16:15:20
- momo
- 446493 View
- 738 Score
- 10 Answer
- Tags: node.js exception-handling serverside-javascript
14 Answered Questions
[SOLVED] How to run Node.js as a background process and never die?
- 2011-01-25 17:53:33
- murvinlai
- 718020 View
- 474 Score
- 14 Answer
- Tags: node.js linux background-process
17 Answered Questions
[SOLVED] How to decide when to use Node.js?
- 2011-02-21 05:20:51
- Legend
- 507684 View
- 2198 Score
- 17 Answer
- Tags: javascript node.js web-applications
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:
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:
A full working example using the above function:
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:
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 thesudo
. That will add the redirect when the machine boots up. You don't needsudo
in/etc/rc.local
because the commands there are run asroot
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 asroot
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 asroot
. However, security best practices are to never run a server asroot
.@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()
andprocess.setuid()
in the app itself to downgrade its permissions to those of a specially creatednodejs
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 linePlease 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 thechmod
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 fromiptables
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 ICreated an SSL Certificate Signing Request (CSR) via OpenSSL
Changed the
location
in/etc/nginx/conf.d/example_ssl.conf
toFormatted the cert for nginx by
cat
-ing the individual certs together and linked to it in my nginxexample_ssl.conf
file (and uncommented stuff, got rid of 'example' in the name,...)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.