I'm starting a webserver as non-root using a systemd unit file.
I am getting listen tcp :80: bind: permission denied
even though I already ran
setcap cap_net_bind_service=+ep
on the executable.
In an example unit file on the internet I found
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
to be used in the unit file. So I tried that out, and suddenly the application can bind port 80.
What does that tell me? setcap
is old/deprecated/ignored? Only by systemd or by Linux in general?
Best Answer
It's correct to say that in general systemd will not work with file capabilities managed with
setcap
and will require you to configure them as part of the service unit instead.So it's not like
setcap
is completely deprecated... (There might be valid uses for it outside of services launched by systemd.) But it doesn't really work for systemd services, at least.In fact, file capabilities (set by
setcap
) were always dubious and questionable, from the start... They require the use of "inheritable" capabilities, which were somewhat poorly conceived and had many shortcomings... The kernel feature of "ambient" capabilities was introduced to solve many of these issues and it's what newer systems are adopting (systemd included here, as you can see, you're settingAmbientCapabilities=
for your service to manage to be able to bind to low ports.)The topic of capabilities is fairly complex... For a perhaps gentler introduction to this issue, you might want to check "Inheriting capabilities" at LWN. For the full gory details (including some algebraic notation on the capability sets), refer to the capabilities(7) man page.