I think I like systemd's DynamicUser feature (under the right circumstances)

July 24, 2019

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.)

Written on 24 July 2019.
« ZFS pool imports happen in two stages of pool configuration processing
How 'zpool import' generates its view of a pool's configuration »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Jul 24 22:32:38 2019
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.