[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: restarting instanced systemd services on upgrade



On Wed, 11 Nov 2020 at 09:32:46 +0900, Norbert Preining wrote:
> once again, thanks a lot. I have now tried out your suggestion and it
> works nicely. Just to make sure, I have now the following units, see
> below. I am aware that the system instantiation service onedrive@ is not
> optimal since it expects $HOME to be /home/%i, but let us leave this
> aside for now. I will document other options like lingering etc.

I still think doing this as a user service (like pulseaudio, gpg-agent,
dbus-daemon --session, rygel, flatpak-session-helper, tracker-store, etc.)
would be a better approach to use by default: that sort of thing is exactly
what `systemd --user` is designed for.

Or perhaps it would make sense to have both implementations, like you said
you've done, but swap round their enabledness: enable the user service by
default, but provide example system units (disabled by default) that can
be used by sysadmins who consider the advantages of running this as a
system service to outweigh the disadvantages?

I assume this package is a FUSE filesystem (or some other daemon) for access
to Microsoft OneDrive? It might be useful to compare it with other
implementations of the same sort of thing. In GNOME, OneDrive access is not
currently implemented (https://gitlab.gnome.org/GNOME/gvfs/-/issues/273);
but if it was, it would be a backend for gvfs, which is a collection of
user services (gvfs already knows how to access Google Drive, but not
OneDrive). One of the motivations for `systemd --user` and the D-Bus
"user bus" (which is one per `systemd --user`) was to make services like
gvfs available to non-GUI user processes like cron jobs.

It looks as though the system service would have to be enabled manually
on a per-user basis *anyway*, because the package can't know which users
it is meant to be enabled for; so perhaps the best way would be something
like this in README.Debian, and arranging the packaging so that it becomes
true:

    onedrive.service is run as a per-user systemd service for each
    logged-in user by default. Individual users can disable or enable the
    service for themselves only, by running one of these commands:

        $ systemctl --user disable onedrive.service
        $ systemctl --user enable onedrive.service

    The system administrator can control whether the service is run by
    default for users who have not explicitly disabled or enabled it by
    running one of these commands:

        # systemctl --user --global disable onedrive.service
        # systemctl --user --global enable onedrive.service

    It is also possible to run onedrive as a system-level service on behalf
    of particular users. [explain here why you might want to do that]

    For example, if a system-level instance of onedrive should run for user
    "norbert", the system administrator would:

    - disable the per-user service for the user:
      # runuser -u norbert -- systemctl --user disable onedrive.service

    - then enable a system service that runs as that user instead:
      # systemctl enable onedrive@norbert.service

> /lib/systemd/system/onedrive@.service
> --------------------------------------
...
> After=network-online.target
> Wants=network-online.target
> PartOf=onedrive.target
> 
> [Service]
> ExecStart=/usr/bin/onedrive --monitor --confdir=/home/%i/.config/onedrive

If you are sure you want this to be a system service, this looks
right. However, as you said, this assumes every user's home directory
is /home/${LOGNAME}. It also won't respect the user's ${XDG_CONFIG_HOME}
(it assumes the default ~/.config).

systemd documents that it sets ${HOME} for system services that
have User= (at least in recent-ish versions, I'm not sure how
old this feature is), so you could probably do a bit better by
using --confdir=${HOME}/.config/onedrive (see systemd.service(5)
for full details of how variables introduced by $ are parsed
in ExecStart). However, that's still making an assumption about
${XDG_CONFIG_HOME}.

More generally, any per-user environment variables that have been set
for the user won't be set for system services that happen to run as
the same uid, which could lead to unexpected results. For example, if
users set PATH, XDG_CACHE_HOME, XDG_CONFIG_HOME or LANGUAGE, nothing
that onedrive does will respect those environment variables.

If onedrive wants to access the D-Bus session bus, for example to send
notifications, it also won't be able to do that reliably (but it could
if it was a user service).

For the system service approach, you'll also need a target
/lib/systemd/system/onedrive.target. If you *don't* give the target
an [Install] section:

    # /lib/systemd/system/onedrive.target
    [Unit]
    Description=OneDrive clients
    Documentation=...
    # end of file

but instead give onedrive@.service a Wants on it:

    # /lib/systemd/system/onedrive@.service
    [Unit]
    ...
    After=network-online.target
    Wants=network-online.target onedrive.target

then it will automatically become part of system boot if and only if
at least one instance of onedrive@.service is enabled, which I think is
probably the right thing to do.

> /usr/lib/systemd/user/onedrive.service
> --------------------------------------
...
> After=network-online.target
> Wants=network-online.target
> PartOf=onedrive.target

These will not have any effect (unless you have created a
/usr/lib/systemd/user/onedrive.target that is not visible here, but
that would be pointless because there's only one onedrive.service on the
per-user instance). systemd as pid 1 and `systemd --user` are separate
service managers, with entirely separate ecosystems of units: neither
can see units that were configured for the other.

    smcv


Reply to: