97

I'm running an instance of Debian on Amazon EC2 with Node.js installed. If I run the code below:

http = require('http');

http.createServer(function (request, response){
  response.writeHead(200, {'Content-Type':'text/plain'});
  response.end('Hello World\n');
}).listen(80);
console.log("Running server at port 80");

I get the output below which tells me there's another process listening at port 80:

Running server at port 80

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: listen EACCES
    at errnoException (net.js:901:11)
    at Server._listen2 (net.js:1020:19)
    at listen (net.js:1061:10)
    at Server.listen (net.js:1127:5)
    at Object.<anonymous> (/home/admin/nodetests/nodetest.js:6:4)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

Now when I check to see if there's a process (as root in case anything is hidden) listening on port 80 using:

netstat -tupln

I get the below output, which tells me theres nothing listening at port 80:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1667/sshd       
tcp6       0      0 :::22                   :::*                    LISTEN      1667/sshd

I should note that the debian has port 80 open as an inbound rule if that makes a difference.

My question is: What am I doing wrong? How come I can't identify the process listening to port 80? Why is it blocked in Debian? What steps should I take to get the code running correctly?

hexacyanide
  • 88,222
  • 31
  • 159
  • 162
Brian Yeh
  • 3,119
  • 3
  • 26
  • 40

8 Answers8

203

The error code EACCES means you don't have proper permissions to run applications on that port. On Linux systems, any port below 1024 requires root access.

hexacyanide
  • 88,222
  • 31
  • 159
  • 162
  • 5
    thus, sudo node myapp.js will do it if you have authorization to use sudo (just tacking it on for any beginners). – AlexMA Oct 06 '13 at 02:29
  • 24
    @AlexMA but running a server as root is a big no no – Patrick Evans Oct 06 '13 at 04:22
  • 1
    Then how do you run node on port 80 though? Should you just... not and use a proxy? – AlexMA Oct 07 '13 at 12:35
  • 9
    @PatrickEvans I suppose the best practice would be to run on a different port and just set up a port-forwarding rule as mentioned here: http://stackoverflow.com/questions/16573668/best-practices-when-running-node-js-with-port-80-ubuntu-linode – AlexMA Oct 08 '13 at 13:16
75

Instead of running on port 80 you can redirect port 80 to your application's port (>1024) using

iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000

This will work if your application is running on port 3000.

Kamrul
  • 7,175
  • 3
  • 31
  • 31
  • 1
    did this. Found out that you have to be root to run iptables in a fresh debian installation, otherwise $PATH won't point to it. – Brian Yeh Sep 26 '13 at 01:59
  • Yep this was probably the easiest way to do it. I'm on Google Cloud Compute which gave me issues when touching Port 80. This was great. Thanks. – Andy May 04 '17 at 17:14
  • This should be the accepted solution. Running the web server as sudo is dangerous, potentially giving an attacker root access if there is any vulnerability in the application; also, if the application were to create any files, they'd be inaccesible for other users, making you use `sudo` even more. – Jk041 Oct 02 '17 at 10:31
  • Not sure why, but on Ubuntu 14.04 this did not work for me. I now use port forwarding via ssh, which is just as easy. I posted [an answer below](https://stackoverflow.com/a/49004892/2072165). – panepeter Feb 27 '18 at 09:12
23

Short answer: You can allow node access to that port using:

setcap 'cap_net_bind_service=+ep' /path/to/nodejs

long answer

Edit:

May not work on new node versions

Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
  • that did the trick. @LinuxMint - sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/node – Combine Feb 11 '16 at 10:43
  • Sometimes an update will change the location path to node, and this will stop working. So you'll need to run it again for the new path to node. – steampowered Aug 11 '18 at 17:20
  • It looks like this will no longer work past node version 8. https://github.com/nodejs/node/issues/22648 – timaw May 08 '19 at 19:23
6

Note that if you have apache running, you can create a reverse proxy on a vhost. If your node is running on port 8080:

<VirtualHost 127.0.0.1:80>
        ServerName myLocalServer

        ProxyPass        /  http://localhost:8080/
        ProxyPassReverse /  http://localhost:8080/
</VirtualHost>

Of course, add server to /etc/hosts:

127.0.0.1    myLocalServer

You will need to enable the relevant apache modules:

sudo a2enmod proxy_html
sudo a2enmod proxy_http
sudo a2enmod proxy_connect
sudo a2enmod proxy_ajp
sudo service apache2 restart

...and now you can connect to http://myLocalServer.

Redsandro
  • 11,060
  • 13
  • 76
  • 106
3

For those looking for a quick and easy solution for a development environment, port forwarding via ssh can be a nice alternative:

ssh -L 80:localhost:3000 yourusername@localhost -N

This forwards port 80 on localhost to port 3000 on localhost.

It needs to be run as root (privileged port). To cancel it, simply hit ctrl-c in the terminal. (You can add the -f flag to have the command run in the background, but then you need to find it again to kill it).

This solution requires you to have an ssh server running locally. It can be done quickly, but please bear in mind the security implications if you are on a shared network. You might want to apply at least some level of additional security (disable password & root login).

I personally only ever use this on my local machine. I'm not sure how it affects the processing speed of your requests if you run this on production, maybe someone has an idea. Anyway, you would need to make sure this command keeps running all the time, which introduces more headaches. For production environments, I suggest using a reverse proxy like nginx.

panepeter
  • 3,224
  • 1
  • 29
  • 41
2

the hexacyanide answer is right. but is there any solution to make this work?

the answer is yes.

how?

you can use a reverse proxy for example run a nginx reverse proxy on port 80 and pass the proxy to destination ip:port that node use it.

you can set this up using docker container that makes life even easier. this is the official build of nginx in docker hub that you can pull it.

there's even more benefits in using reverse proxy that you can google it.

Ali_Hr
  • 4,017
  • 3
  • 27
  • 34
0

I have got the same error and I tried running my application using sudo and it worked for me.

without sudo

mansi@mansi:~/NodePractice$ node myFirst.js 
events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: listen EACCES 0.0.0.0:80
    at Object.exports._errnoException (util.js:870:11)
    at exports._exceptionWithHostPort (util.js:893:20)
    at Server._listen2 (net.js:1224:19)
    at listen (net.js:1273:10)
    at Server.listen (net.js:1369:5)
    at Object.<anonymous> (/home/mansi/NodePractice/myFirst.js:6:4)
    at Module._compile (module.js:410:26)
    at Object.Module._extensions..js (module.js:417:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)

and with sudo

mansi@mansi:~/NodePractice$ sudo node myFirst.js 
^C
-2

The error code EACCES means you don't have proper permissions to run applications on that port. On Linux systems, any port below 1024 requires root access.

Run the program with sudo permision. Run sudo su command before running the program.

Bless
  • 5,052
  • 2
  • 40
  • 44