88

My aim is to run Node.js on port 80. This is because I am finding node.js is being blocked from certain networks which do not allow traffic from any other port.

It appears that the best way to do this is by proxying Apache through Node.js. I have tried using node-http-proxy to do this but I have not had any luck.

The code I am using is here:

var util = require('util'),
    http = require('http'),
    httpProxy = require('http-proxy');

httpProxy.createServer(9000, 'localhost').listen(80);

http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

But I keep getting the error "Address in use" for port 80. I must be doing something wrong.

How do I proxy Apache through node.js using node-http-proxy? Will this enable me to run node.js on port 80? And is node-http-proxy the best way to achieve this?

Thank you.

Kit
  • 4,095
  • 7
  • 39
  • 62

9 Answers9

132

run your app on a high port 8080 or whatev then

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

If you are not using ngnix or apache

fullstacklife
  • 2,031
  • 3
  • 16
  • 13
66

The simplest solution: safely configure your node app to run on port 80.

  • sudo apt-get install libcap2-bin
  • sudo setcap cap_net_bind_service=+ep /path/to/node
  • Ta da! You're done.

Why do I like it?

  • You don't have to use apache or nginx
  • You don't have to run your application as root
  • You won't have to forward ports (and handle that each time your machine boots)

Reference Link: https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps (A great article on how to set up your node app on cloud hosting).

Kyle Chadha
  • 3,741
  • 2
  • 33
  • 42
  • 1
    Kudos for not only providing the most elegant solution, but providing a legit reference link. – Gor Jan 25 '15 at 04:25
  • This is just what I needed. I spent a while scratching my head trying to figure out why I could launch my Express HTTP server in node on every port except 80. – nick Feb 03 '15 at 22:42
  • Excellent! One just needs to remember to do this again if he upgrades Node (e.g. with nvm). – Jackson Apr 23 '16 at 03:25
  • This is also useful for other platforms besides node. – Charles Wood Jun 23 '16 at 15:01
  • It did not work for me. I did sudo setcap cap_net_bind_service=+ep /usr/bin/nodejs (for mac). When I do netstat -tlpn it still shows apache2 on port 80 and nodejs on 8000. What am I doing wrong? – codeinprogress Apr 19 '17 at 12:58
  • @codeinprogress you still have to tell your node app to run on port 80 – Kyle Chadha Apr 27 '17 at 14:07
31

What you need to do is have 2 ip's for the server you are running. Apache has 1 ip bound to port 80 and then node.js has the other ip bound to port 80.

Using node and its listen directive has 2 values eg. .listen(80, NODEJS_IP or DNS NAME);

Some other advice.

I would not use apache with nodejs as it's not evented. So this really isn't recommended. I would actually look into using NGINX as its a much better pairing with Node.

PaulM
  • 3,281
  • 3
  • 28
  • 38
  • @PaulM. Thanks. How do I go about binding the secondary IP to port 80 and node.js rather than Apache? – Kit May 24 '11 at 10:46
  • With your dns have something like www.domain.com for 1 ip and chat.domain.com for the other ip. In apache listen to the first ip address: Listen vvv.xxx.yyy.zzz:80. Then with node do .listen(80, chat.domain.com). This is the setup that I am using and I have had no problems with any corporate firewalls, etc. – PaulM May 24 '11 at 11:05
  • 1
    I wouldn´t recommend nginx for node. Nginx does not support HTTP 1.1 which means you will not be able to do some WebSocket stuff. When you use node.js, I think you will want to use this really fast ;) – Van Coding May 24 '11 at 11:51
  • 2
    @FlashFan, I'm able to do WebSocket stuff with Chrome just fine with my site. Can you elaborate further? – PaulM May 24 '11 at 13:09
  • @PaulM - I am having troubles trying to bind Apache to a specific IP. I have Q here: http://serverfault.com/questions/273143/binding-apache-to-specific-ip-address/273155#273155 Did you have any issues when you did this? – Kit May 24 '11 at 13:23
  • I've answered. You only need 1 instance of Listen in the apache.conf file. You only need 1 IP bound to apache. – PaulM May 24 '11 at 13:51
21

It is currently not recommended to run node on port 80, as that requires running node as root.

How attached are you to apache? Proxying node through nginx is a tried and true solution, with an nginx-config such as this:

upstream node_cluster {
    ip_hash;   
    server 127.0.0.1:8000;
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
}

server {
    listen 0.0.0.0:80;
    server_name foo;
    access_log /var/log/nginx/foo.log;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;

      proxy_pass http://node_cluster/;
      proxy_redirect off;
    }
}

Nginx documentation:

http://wiki.nginx.org/HttpProxyModule

http://wiki.nginx.org/HttpUpstreamModule

Waquo
  • 840
  • 1
  • 5
  • 6
  • 4
    Plenty of people run node on port 80. Proxying through nginx requires some overhead. Also you don't need root to run on port 80. See here for more info: http://comments.gmane.org/gmane.comp.lang.javascript.nodejs/8959 I'm not running node via root myself. – PaulM May 24 '11 at 13:15
  • Thanks Waquo. I am looking at my options ATM. Nginx may be the way forward. – Kit May 24 '11 at 13:20
  • Look at dryprogrammers answer for how to run Node on port 80 w/o being root. –  Nov 27 '13 at 01:28
  • This answer makes me feel like I can serve both node and php applications from the same server and IP, using different ports for each app, but I'm not so familiar with `nginx` to be sure it it is actually possible... – Loupax Apr 24 '14 at 09:53
  • To test on port 80, I stopped apache2 and needed to run as SUDO. Normal user can not call node with port 80, but root can. Thanks for the info I needed. – Sergio Abreu Oct 14 '22 at 17:23
9

Your code looks like example code in which you're creating a Node-based proxy from port 80 to port 9000, and then creating a Node-based HTTP server on port 9000. (i.e. Node:80 -> Node:9000)

You are getting "address in use" when you launch Node because Apache is already using port 80. If you want to use Apache to proxy, you must use Node on a different port (say 9000) and have Apache listening on port 80 and forwarding the requests to Node on port 9000. (i.e. Apache:80 -> Node:9000)

It looks like the library you're using is for doing the opposite: using Node as the proxy and forwarding requests to Apache. In this case you must configure Apache to run on another port than port 80. (i.e. Node:80 -> Apache:9000).

Are you wanting to do Node:80 -> Apache:9000 or Apache:9000 -> Node:80, in the end?

EDIT after comments: If you want to do Apache:80 -> Node:9000, you can use mod_proxy on Apache and use the ProxyPass/ProxyPassReverse directives, something like

ProxyPass /nodeurls/ http://localhost:9000/
ProxyPassReverse /nodeurls/ http://localhost:9000/  

where nodeurls is the family of URLs you wish for Apache to forward to Node.

nicolaskruchten
  • 26,384
  • 8
  • 83
  • 101
  • Thank you. I am not too sure. Sorry! I want node to run on apache:80. So.. Node:9000->Apache:80. Not too sure if this is correct. – Kit May 24 '11 at 12:20
  • If you want to run Apache on port 80, then you must run Node on another port, say port 9000. In that case, you must configure Apache to forward some of its requests to Node. I would write this as `Apache:80 -> Node:9000` to continue what I've written above. – nicolaskruchten May 24 '11 at 12:24
  • Ah OK. I see. How do I go about getting Apache to forward some of its requests to Node? – Kit May 24 '11 at 12:26
  • See my edits, you'll have to do install a module and configure it. – nicolaskruchten May 24 '11 at 12:28
  • 1
    I think you meant `Apache:80 -> Node:9000` instead of `Node:80 -> Node:9000` in the first line. – Pratik Khadloya Feb 22 '12 at 19:20
7

If you are a non-root user, you cannot run or bind with ports lower than 1024 (in Unix system). To allow non-root user can run node on port lower than 1024 use this command.

$ sudo setcap 'cap_net_bind_service=+ep' $(which node)
Chhaileng
  • 2,428
  • 1
  • 27
  • 24
  • This worked for me. Can someone explain what it's doing? I'd like to understand it at least well enough to undo it if ever needed. – robm Feb 13 '23 at 03:46
3

I was having the same issue, here is how I resolved it using node-http-proxy to listen on port 80, then forward to either express or apache.

https://stackoverflow.com/a/9645091/500270

Community
  • 1
  • 1
gxc
  • 4,946
  • 6
  • 37
  • 55
0

I had the same issue, I just changed my port to 8080 and it worked.

httpsServer.listen(8080, () =>
    console.log(chalk.rgb(208, 60, 240)(`Server listening on port: 8080`))
  );
-6

if you just in develop environment mode

you can su root, then

node index.js or ./node_modules/coffee-script/bin/coffee index.coffee

jiahut
  • 1,451
  • 15
  • 14
  • 3
    I'm no network admin but for security's sake I would highly recommend not running a server with root privileges. – nick Feb 03 '15 at 22:45