使用sudo与ExecStart(systemd)

17

我正在尝试在80端口上使一个node.js网站上线(我使用的是Digital Ocean)。我正在使用systemd文件进行此操作。

我试图在系统启动后自动启动我的Node.js应用程序并将其绑定到端口80。为此,我创建了一个systemd服务文件,并使用以下命令将其启用:

sudo systemctl enable myapp.service

然后,我可以使用以下命令来启动/停止/重新启动我的应用程序:

sudo systemctl start myapp
sudo systemctl stop myapp
sudo systemctl restart myapp
...
ExecStart=/usr/bin/nodejs /var/www/bin/app.js
...

在本地主机上,如果我使用sudo启动网站并在端口80上运行,则可以正常工作,但是没有使用sudo时就不能正常运行。显然,对于低于1024的端口,您需要以root身份运行。

我该如何在ExecStart中允许sudo?或者我完全错了吗?如果是这样,我该如何将表达应用程序放在端口80上?

谢谢,Mike

2个回答

25

默认情况下,Systemd以root身份启动ExecStart=中指定的可执行文件。

但是,如果在服务文件中指定了User=Group=覆盖了该默认设置,并且仍然需要运行需要sudo的可执行文件,则需要在命令前加上您sudo所在目录的绝对路径:

...
ExecStart=/usr/bin/sudo /usr/bin/nodejs /var/www/bin/app.js
...

7

默认情况下,Systemd以root身份启动ExecStart=中指定的可执行文件。这意味着,如果您在服务文件中没有指定User=或Group=,则会特权启动二进制文件。

您可以通过启动id或whoami程序来验证这一点。例如:ExecStart=/usr/bin/idExecStart=/usr/bin/whoami(请注意,程序的路径可能与您的不同)


我确实指定了一个组(非root),但我想保持这种方式,因为不以root身份运行网站是良好的实践。我该如何解决我的问题? - Mike
你需要一个.socket单元来监听特权用户的端口。然后systemd会将socket传递给你的服务。但是,这需要对nodejs进行代码修改才能实现systemd socket激活。 - Umut
我尝试了以下代码:require('systemd');var port = process.env.LISTEN_PID > 0 ? 'systemd' : 3050;app.set('port', port);但是到目前为止还没有成功。 - Mike
1
最终我使用了sudo setcap cap_net_bind_service=+ep /usr/bin/nodejs来允许nodejs在1024以下的端口上发布。 - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接