I have a Node project that needs to run under port 80, but am having issues running the pm2 project with Port 80, the instances of my app run but I get the same predictable issues with EACCESS on Port 80
Error: bind EACCES null:80
at Object.exports._errnoException (util.js:870:11)
at exports._exceptionWithHostPort (util.js:893:20)
at cb (net.js:1302:16)
at rr (cluster.js:594:14)
at Worker.<anonymous> (cluster.js:564:9)
at process.<anonymous> (cluster.js:714:8)
at emitTwo (events.js:92:20)
at process.emit (events.js:172:7)
at handleMessage (internal/child_process.js:689:10)
at Pipe.channel.onread (internal/child_process.js:440:11)
I did some research and tried the setcap approach outlined here, only to run into issues giving node those rights (probably because I made node a symlink to nodejs, which is set to run at port 80):
Failed to set capabilities on file `/usr/bin/node' (Invalid argument)
The value of the capability argument is not permitted for a file. Or the file is not a regular (non-symlink) file
I've tried to run the pm2 instance as sudo, with no success. The process refuses to connect on port 80. Is there an easier way to go about this? Am I missing something in my configuration?
You cannot listen on a port number under 1024 without sudo.
This article was copied form PM2 documentation
http://pm2.keymetrics.io/docs/usage/specifics/
It’s a general rule that you should not run node as root. However only root can bind to ports less than 1024. This is where authbind comes in. Authbind allows non-root users to bind to ports less than 1024. Replace %user% with the user that will be running pm2.
sudo apt-get install authbind
sudo touch /etc/authbind/byport/80
sudo chown %user% /etc/authbind/byport/80
sudo chmod 755 /etc/authbind/byport/80
You should also add an alias to the user that runs pm2 profile, e.g. ~/.bashrc or ~/.zshrc (note you will need to run source ~/.bashrc or source ~/.zshrc immediately after):
+alias pm2='authbind --deep pm2'
Finally ensure that pm2 is updated with authbind:
authbind --deep pm2 update
Or simply pm2 update if you added the alias to your user’s profile.
Now you can start applications using PM2 that can bind to port 80 without being root!
Related
I have a node.js express app running on an Ubuntu 21.04 server.
I run the app with pm2 with a non root user, the app listens on ports 80 and 443, I had the error Error: bind EACCES null:80.
As mentionned in the pm2 documentation, I performed all instructions for ports 80 and 443 and it works like a charm.
I also ran pm2 save and pm2 startup systemd to make the app autostart when server reboot.
But when the server reboot:
pm2 list shows myApp with an online status, but I encounter again the error: Error: bind EACCES null:80 and the app is not working.
Then if I pm2 kill and pm2 start myApp again, then it works well...
Do you know why on server reboot the pm2 starts not well but if I start it manually it's ok?
Thanks
I found the solution in this post from the pm2 team on github, this is because of the authbind when listening on port 80.
Edit the config file created by the pm2 startup procedure (the file should be at /etc/systemd/system/pm2-<your-user>.service, and add /usr/bin/authbind --deep at the begining of the 3 commands ExecStart, ExecReload and ExecStop, leaving the rest of the command. For example in my config file:
ExecStart=/usr/bin/authbind --deep /usr/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/bin/authbind --deep /usr/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/bin/authbind --deep /usr/lib/node_modules/pm2/bin/pm2 kill
Then app auto-restarts well with non root user after server reboot!
The Nas I used at home has installed Node JS v12 from Synology's package center. So I thought it would be cool to create a Node JS http webserver and study myself into back-end and front end development.
Create volume1/path_to_your_app/app.js and let the http server listen to port 8080.
Next, With Powershell I could login with my Synology (admin) account's [username] and [password] into the Nas through ip-address from home. For accessing with ssh in Synology's cofiguration/Terminal the ssh-service must be checked. The default portnumber is 22, I changed this to for example 8822. Next, from Powershell I could now run the command:
ssh username#192.168.1.44 -p8822
Next password will be prompted
From Synology's shell I could now navigate to the file, run it and view it in my browser at 192.168.1.44:8080/.
cd /volume1/path_to_your_app/
node app.js
Next I setup port forwarding to host the webserver online. In my routers settings/port forwarding ipv4/ my nas is defined under an ip-address 192.168.1.44. At the Nas's application configuration I added a new rule under TCP protocol on port 8080. It only works for port 8080 (as far as I could get it workingfor now) because this is an experimental port. I could now access my webserver on my router's WAN-IP:8080/.
After I exit the Synology's shell (ctrl+c) my application also stops running. I was not able to install forever from npm to keep the server running. However from this page I found a solution. I had to create an upstart file from Synology's shell in the /etc/init folder.
cd / (go back to root)
cd /etc/init/
sudo vi yourappname.conf
the I copy/pasted this code in the (.conf) file AND editted the parameters to my enviroment:
#!upstart
description "your app name"
start on started mountall
stop on shutdown
# Automatically Respawn:
respawn
respawn limit 99 5
env NODE_ENV=development
# Warning: this runs node as root user, which is a security risk
# in many scenarios, but upstart-ing a process as a non-root user
# is outside the scope of this question
chdir /volume1/path_to_your_app/
exec node /volume1/path_to_your_app/app.js >> /var/log/yourappname.log 2>&1
Now I could start and stop the upstart script manually from Synology's shell and it keeps on running even after I exit the Synology's shell. I also inserted "chdir /path_to_your_app/" in the script before "exec" because it changes the directory from where Node JS is running to the directory from your app. I don't know what security risks are from the warning in the script.
sudo start yourappname
sudo stop yourappname
Debugging my Node JS application i do with the commands:
sudo tail -f /var/log/yourappname.log
I don't know why you wrote the Warning because it can be solved by one command
setuid <username>
i want to run my node.js application on port 80 without running it as root
$> which node
/usr/bin/node
I have tried to use setcap but it's not working:
$> sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/bin/node
Failed to set capabilities on file `/usr/bin/node' (Operation not
permitted)
The value of the capability argument is not permitted for a file. Or
the file is not a regular (non-symlink) file
What am i doing wrong ?
Ports below 1000 require sudo privilege. You can use the following command to allow it to bind to port 80 without sudo:
sudo setcap 'cap_net_bind_service=+ep' `which node`
Finally, I have used port redirection, not with iptables but with ufw
https://serverfault.com/questions/238563/can-i-use-ufw-to-setup-a-port-forward
I have created node application and I want to deploy it on AWS.
I have setup project and want to make node permanent so I have installed pm2 globally, but when I tried to start node app with pm2 with this command
sudo pm2 start index.js
It's giving me error:
sudo:pm2 is not a command
Without sudo I can't start server.
Apparently pm2, and other global modules aren't in your root path. You can pass the PATH variable like this:
sudo env PATH=$PATH pm2 start index.js
This should do what you want.
Though mainly I would suggest not doing this, as probably you wouldn't want your application to run with root user, rather it's own isolated and limited user so in case vulnerabilities, the damage would be limited.
If you want to run pm2 on your machine startup, then you can use pm2 startup command which will instruct you how to do this properly.
Also if you are running your application as root, so you can listen on port 80, then that's the wrong way. I suggest have a look at this question. There are some good suggestions such as using ip tables to forwad port 80 traffic to another port which wouldn't require your application running on root.
I have a node application which runs fine if I manually putty into the gcloud computeVM and run it.
Here are the complications (all realted to unix) :
1.) I have a domain name. So I added the dns zone record to point to the above VM.
2.) For the compute VM to respond, there should be process listening on 80
3.) If we follow the https://cloud.google.com/nodejs/getting-started/run-on-compute-engine#download_app , it specifies to run the app on 8080.
4.) For ports < 1024, it requires root privileges to open up ports.
5.) So from npm start, I changed the start up script to use "sudo npm start"
6.) Then it gave the following error : my-app-instance supervisord: nodeapp sudo: no tty present and no askpass program specified
7.) If I have to "sudo visudo" everytime and add the "username ALL = NOPASSWD:" everytime I restart the instance after deployment , its something which I would least prefer.
I have included the relevant portion of the stratup-script for more info :
# Install app dependencies
cd /myrepo/opt/app/servers
sudo npm install
# Create a nodeapp user. The application will run as this user.
useradd -m -d /home/nodeapp nodeapp
chown -R nodeapp:nodeapp /myrepo/opt/app/servers
# Configure supervisor to run the node app.
cat >/etc/supervisor/conf.d/node-app.conf << EOF
[program:nodeapp]
directory=/myrepo/opt/app/servers
command=sudo npm start
autostart=true
autorestart=true
user=nodeapp
environment=HOME="/home/nodeapp",USER="nodeapp",NODE_ENV="production"
stdout_logfile=syslog
stderr_logfile=syslog
EOF
A.) My requirement is simple : My google domain points to the above compute VM now. whenever the user types www.domainname.com, it should take him to the website without any port numbers in the url. How to open port 80 with a simple modification of start-up script(preferred) ?
B.) And also if I have to go with deploy.sh specified in the tutorial, will it get executed automatically ? Or if I have to execute it automatically , whats the procedure.
Note : I am not unix expert. Any help would be appreciated.
Look into using a reverse proxy. This allows you to run your app without root privileges on a port like 8080, and have a privileged HTTP server (like Apache or Nginx) running on port 80 and proxying traffic to your app. This is common practice, and much more secure than running your app with root privileges.