systemd start as unprivileged user in a group

I’d like users in group foogroup to be able to:

  • systemctl start foo.service,
  • systemctl stop foo.service,
  • systemctl status foo.service, and
  • journalctl -u foo.service

without using elevated privileges. Is that possible?


I have a systemd service which looks like:

[Unit]
Description=foo service

[Service]
Type=simple
ExecStart=/bin/sleep infinity
User=foobot
Group=foogroup

Where foobot is a system user.

I know we can install the unit file to ~/.config/systemd/user/ to allow an unprivileged user to use systemd, but this doesn’t really help a group.

Note: I plan on using the sd-bus API from libsystem-dev and cockpit so adding systemctl to /etc/sudoers isn’t going to help.

I don’t care as much about systemctl enable, it’s fine if I need elevated privilages for that.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

This was the solution I eventually came up with. I created:

/etc/polkit-1/localauthority/50-local.d/service-auth.pkla
---
[Allow foogroup to start/stop/restart services]
Identity=unix-group:foogroup
Action=org.freedesktop.systemd1.manage-units
ResultActive=yes

Note that this specifically works for polkit <106 as used in Debian/Ubuntu. Other distributions use a newer version of polkit which would have done something like this:

/etc/polkit-1/rules.d/foogroup.rules
---
polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        subject.isInGroup("foogroup")) {
        return polkit.Result.YES;
    } });

If you want to restrict it to a single service and only start/stop/restart, use something like this:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        subject.isInGroup("foogroup")) {
        if (action.lookup("unit") == "foo.service") {
            var verb = action.lookup("verb");
            if (verb == "start" || verb == "stop" || verb == "restart") {
                return polkit.Result.YES;
            }
        }
    }
});

(from https://wiki.archlinux.org/title/Polkit)

Method 2

I was looking for a solution to the same and couldn’t find one that really satisfies me. A satisfying solution would be to have group support in systemd. But I found this workaround. Let’s assume the users you want to grant access to are ann, ben, and chris. They are all shall be in a group awesomeproject.

  1. Create a new user awesomeproject and add the users to the group of awesomeproject.
sudo adduser awesomeproject
sudo usermod -a -G awesomeproject ann
sudo usermod -a -G awesomeproject ben
sudo usermod -a -G awesomeproject chris
  1. Add all users of the group to the sudoers for systemctl of that new user.
sudo visudo

The entries have to look like this:

ann    ALL=(awesomeproject) NOPASSWD: /bin/systemctl
ben    ALL=(awesomeproject) NOPASSWD: /bin/systemctl
chris  ALL=(awesomeproject) NOPASSWD: /bin/systemctl

Instead of putting them in /etc/sudoers, depending on the distribution, it may be better to put them in /etc/sudoers.d/awesomeproject instead using sudo visudo -f /etc/sudoers.d/awesomeproject.

  1. Manage permissions on files and directories accordingly so that members of the group awesomeproject have access to the corresponding files and directories in ~awesomeproject.
  2. The following command should now work for ann, ben, and chris:
sudo awesomeproject systemctl ...


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x