Run node js on ports 80 without running as root - node.js

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

Related

How to run an Ubuntu NFS V4 kernel server in an Ubuntu docker instance without port mapper?

I need to operate a NFS server in docker in pure V4 mode, i.e. without portmapper port 111. (Reason: NFS server in Docker in WSL2 in Windows.)
I found instructions how to operate the Ubuntu default kernel NFS server without port 111 being open:
From https://peteris.rocks/blog/nfs4-single-port/
$ sudo vim /etc/default/nfs-kernel-server
...
RPCMOUNTDOPTS="--no-nfs-version 2 --no-nfs-version 3 --nfs-version 4 --no-udp"
RPCNFSDOPTS="--no-nfs-version 2 --no-nfs-version 3 --nfs-version 4 --no-udp"
...
$ sudo systemctl disable --now rpcbind.service rpcbind.socket
$ sudo systemctl mask rpcbind.service rpcbind.socket
However, this instructions rely on the commands "systemctl disable/mask" which are not available in my Ubuntu docker image, as there's no systemd or init around naturally in docker. When I exclude versions 2 and 3 in /etc/default/kernel-server and start nfs, I get the error message:
Not starting: portmapper is not running
Questions:
How can I run a pure NFS V4 tftp server in docker (Ubuntu) that does not need portmapper / port 111 ?
How can I do systemctl disable --now rpcbind-service rpcbind-socket and systemctl mask epcbind-service rpcbind.socket when I have no systemctl available ?
Do I maybe need to patch /etc/init.d/nfs-kernel-server start ?
Are there better alternatives to nfs-kernel-server for a pure V4 mode ?
Thanks very much.
Solution:
A) Disable check for rpcbind in init script
sudo vim /etc/init.d/nfs-kernel-server
Remove 8 lines near #See if rpcbind is running ... if ...fi
B) Use --privileged when starting rocker run

Can't run pm2 process with Port 80

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!

How to open port 80 for a node.js application without deploy.sh file on gcloud?

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.

Start app as root with pm2

I have a daemon that must be run as root on startup.
I use pm2 to start other apps but can not figure out if it can start an app as root. Can it be done?
If not, what are my options?
I had problems with sudo pm2 start api, but this was since pm2 was already running without sudo privileges, therefor you need to run:
pm2 kill
sudo pm2 start api
This kills the pm2 deamon first, so that it starts in sudo, but then you need sudo for ALL pm2 commands afterwards, like: sudo pm2 ls
If you only need your daemon to be run as root in order to access a port number (such as 80 or 443), the pm2 documentation recommends using authbind. So, if you want the user yourusername to have access to port 80, run:
$ sudo apt-get install authbind
$ sudo touch /etc/authbind/byport/80
$ sudo chown yourusername /etc/authbind/byport/80
$ sudo chmod 755 /etc/authbind/byport/80
$ authbind --deep pm2 update
And then use authbind --deep pm2 instead of pm2. The documentation suggests setting up an alias.
I would recommend:
sudo pm2 start index.js
OR
pm2 start 'http-server' /var/www -p 80
sudo pm2 startup
pm2 save
OR
pm2 start 'which http-server' /var/www -p 80
To start it on your HTTP Port
Also, I always put -i 0 at the end - this starts up as many worker processes as you have cores. Check THIS
It is not always necessary to start PM2 as root. If you have PM2 as root and the cli module installed, security is a big risk. This is only required if you're starting your app on a port between 1 and 1024
Wasted about an hour
On AWS EC2 machine, one system was in inconsistent state due to earlier installations, that forced sudo elevations in the application for all commands to OS, like sh, etc.
pm2 was running as root:
ps aux | grep pm2
# root ... PM2 v4.1.2: God Daemon (/root/.pm2)
Now pm2 is running as ubuntu:
ps aux | grep pm2
# ubuntu ... PM2 v4.1.2: God Daemon (/home/ubuntu/.pm2)
Below commands worked:
sudo pm2 kill
sudo npm remove pm2 -g
sudo npm i -g pm2#latest
sudo pm2 update
sudo chown -R ubuntu:ubuntu /home/ubuntu/.pm2
Hope that helps
You should start pm2 as a root, (sudo pm2 start app.js), then your app will start as a root
First, install pm2 globally.
Then set root permissions to pm2 using this command
sudo chown ubuntu:ubuntu /home/ubuntu/.pm2/rpc.sock /home/ubuntu/.pm2/pub.sock
you might consider routing your traffic with iptables, since there is a reason behind this errror
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

Amazon EC2 - Apache server restart issue

When i run this command
sudo /etc/init.d/httpd restart
it gives below error
Stopping httpd: [FAILED]
Starting httpd: (98)Address already in use: make_sock: could not bind to address [::]:80
(98)Address already in use: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
Unable to open logs [FAILED]
i checked running programs at port 80 by using
netstat -lnp | grep :80 (it gives below output)
tcp 0 0 :::80 :::* LISTEN 21739/httpd
why i am not able to stop stop apache by using sudo /etc/init.d/httpd restart?
below commands work without issue
sudo apachectl stop
sudo apachectl start
i am using linux micro instance of amazon ec2
I ran into this problem when I installed apache from source, but then tried to run
$ sudo /etc/init.d/httpd restart
which was using a pre-installed version of apache. The stop directive in /etc/init.d/httpd was not removing the httpd.pid file that was created when starting the source-installed version of apache.
To determine if this is also the reason for your problem, find where the httpd.pid file is getting set when you run
$ sudo apachectl start
If you installed from source and apache2 is living in /usr/local/apache2, then the httpd.pid file should get created in /usr/local/apache2/logs. When you stop apache by running
$ sudo apachectl stop
this file should get removed. So to test if the httpd.pid file is causing your problem, start apache by calling
$ sudo apachectl start
and locate the httpd.pid file. Then try stopping apache by using
$ sudo /etc/init.d/httpd stop
If the original httpd.pid file is still present, then that is why apache is unable to start when you use
$ sudo /etc/init.d/httpd start
To get my /etc/init.d/httpd file to work correctly, I explicitly put the call to apachectl in the start and stop methods:
#!/bin/bash
# /etc/init.d/httpd
#
# Path to the apachectl script, server binary, and short-form for messages.
apachectl=/usr/local/apache2/bin/apachectl
httpd=/usr/local/apache2/bin/httpd
pid=/usr/local/apache2/logs/httpd.pid
prog=httpd
RETVAL=0
start() {
echo -n $"Starting $prog: "
$apachectl -k start
RETVAL=$?
echo
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
$apachectl -k stop
RETVAL=$?
echo
}
I tried this and it works:
sudo fuser -k -n tcp 80
sudo service httpd start
Hope this will help you!
Cheers
I feel its better to kill the process itself, find out the process id and kill it and then do a fresh start, it should work fine
I have had this issue very rarely over the last couple years with a server I've been managing. Unfortunately, if you are getting FAILED after trying to restart, the process that's managing the connection on port 80 won't release it's hold on that port.
I would try a full "sudo /etc/init.d/httpd stop" wait for that to finish or fail.
If that doesn't fix it you'll have to restart the server completely. Hopefully, it's configured to start everything up automatically on restart, but that isn't guaranteed.
"apachectl" is also great tool for Apache, but it may not be on this server, it depends on the install and linux distro used.
If after rebooting the server, apache still fails to start, something bad has happened. I'd consider pulling all the website and conf files for creating a new server at that point, but the apache start, and then failed message output should give you some idea of where to look in the Logs about why it cannot start.

Resources