Our Prometheus metrics system involves a lot of daemons that do things like generate metrics, both official daemons and various third party ones . Many of these daemons and the things they do are essentially stateless, because they can be and it makes them simpler. I was recently setting up such a daemon (a new one) on my office workstation, and as part of that I wanted to pick a UID for it to run as. I consider this particular daemon slightly more risky than usual, so I didn't want to go with either
root
(it doesn't need that much power) or the '
prometheus
' user, which is not root but does wind up owning things like the Prometheus metrics data storage. At about the time I was looking through my
/etc/passwd
to try to find a user that I was comfortable with and that would work, a little light went on in my mind and I remembered that systemd services can use dynamic users .
Stateless daemons with no special permissions requirements are an ideal match for dynamic users, because basically I just want a generic non-root user. The user doesn't need to have any special privileges, and it doesn't need a stable UID or GID because it will never have anything on disk (or at least, not outside of brief uses of
/tmp
). Systemd making these UIDs and GIDs up on the fly saves me the effort of creating one or more new users, and as you can see, having to explicitly create new users is enough annoyance that I might not do it at all.
(The other advantage of dynamic users here is that if I decide to stop using a daemon, I'm not left with a stray user and group to clean up at some indefinite point in the future.)
Switching my
.service
file from a '
User=
' line to '
DynamicUser=yes
' basically just worked. After a daemon restart, the daemon was running happily under its new unique UID with everything working fine. The daemons I converted had no problems running other programs or making network connections, either.
You don't have to restrict a
DynamicUser
service to standard Unix 'regular UID' permissions (well, somewhat less than that, since systemd adds extra restrictions). I run Prometheus's Blackbox exporter as a non-root user but explicitly augment its capabilities with
CAP_NET_RAW
so that it can send and receive ICMP packets:
[Service] [...] CapabilityBoundingSet=CAP_NET_RAW AmbientCapabilities=CAP_NET_RAW
This still works fine with it converted from '
User=prometheus
' to '
DynamicUser=yes
'.
After this positive experience, I'm probably going to start making more use of '
DynamicUser=yes
'. If a stateless thing doesn't have to run as root, switching it to using a dynamic user is both pretty trivial and a bit more secure.
(Systemd theoretically supports dynamic users for services with some state, but there can be problems with that .)