Enable systemd user service via home-manager for package providing service unit

I want to enable a systemd user service with home-manager for a package that includes a service unit like share/systemd/user/xwayland-satellite.service. I included the package to home.packages and systemd seems to see the service unit:

systemctl --user status xwayland-satellite.service
○ xwayland-satellite.service - Xwayland outside your Wayland
     Loaded: loaded (/home/xxx/.nix-profile/share/systemd/user/xwayland-satellite.service; disabled; preset: ignored)
     Active: inactive (dead)

Nov 22 14:59:00 ito systemd[1723]: xwayland-satellite.service: Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing.

I don’t understand why systemd complains about missing ExecStart because the unit has one:

systemctl --user cat xwayland-satellite.service | grep ExecStart
ExecStart=/nix/store/33cbxy5axb390dgbgy2c2nw7b8j5yiw4-xwayland-satellite-0.5.0-02f3054/bin/xwayland-satellite

What can I do to address the issue of systemd believing that there is not ExecStart?

The next question is, how can I enable the service declaratively with home-manager, without replicating the service unit definition (which of course will work)?

What I’m looking for is a declarative way to do systemctl --user enable xwayland-satellite.service.

Any ideas?

Try systemd-analyze verify --user xwayland-satellite

Also please share all the config you have related to this package or service

Thanks, systemd-analyze --user verify $HOME/.nix-profile/share/systemd/user/xwayland-satellite.service outputs nothing.

Anyhow, here is the service unit, which comes with the package:

systemctl --user cat xwayland-satellite.service
# /home/xxx/.nix-profile/share/systemd/user/xwayland-satellite.service
[Unit]
Description=Xwayland outside your Wayland
BindsTo=graphical-session.target
PartOf=graphical-session.target
After=graphical-session.target
Requisite=graphical-session.target

[Service]
Type=notify
NotifyAccess=all
ExecStart=/nix/store/33cbxy5axb390dgbgy2c2nw7b8j5yiw4-xwayland-satellite-0.5.0-02f3054/bin/xwayland-satellite
StandardOutput=journal

[Install]
WantedBy=graphical-session.target

To be precise: I havent written the service unit. It comes from the package itself with the output share/systemd/user/xwayland-satellite.service. And systemd knows about it, because the package with the unit is installed in my home-manager profile.

I now be sure that the error message below comes from messing up the package provided service unit and providing some fragment by own in order to enable/start it. I cleaned it up by home-manager switch and doing systemctl --user daemon-reload which leads to an environment which only contains the package provided service unit (see above for its definition):

You make it WantedBy=default.target. systemctl enable just a fancy way of doing precisely that imperatively.

That error is indeed confusing. Did it come up when you tried to manually start it or why is it there?

Does it work if you start it manually via systemctl start --user?

Thank you. This is completly clear to me, as it is documented by systemd.

To make this more evident:

  • The package I’m referring to is xwayland-satellite provided by the repo
  • It is not my package
  • I’m just using it in home-manager via home.packages
  • It includes a service.unit share/systemd/user/xwayland-satellite.service
  • The service unit is already visible to systemd thanks to NixOS and home-manager
  • I’m out of control of service unit
  • I’m looking for a way to delaratively enable it, analogous to systemctl --user enable xwayland-satellite

Furthermore, I cannot define a service unit, including WantedBy=default.target, because that way I will redefine the existing unit (provided by the package), effectively shadowing the package service unit.

I cannot define a unit using overrideStrategy = asDropin because that way the unit won’t get enabled. And even more specifically, home-manager does not support overrideStrategy but anyhow I tried to create such an override file (just be sure). It does not help.

Further ideas?

Override the package perhaps. But yeah this is why hm sucks for systemd service management.

Thanks in advance. This what I’m doing now, because I’m out of ideas with this.

Why not?

Then it should. There must be a method to enable package-provided systemd user services.

How exactly did you create the override?

I mean there’s hacks you could do such as a systemd oneshot service that enables all desired services but this really ought to work declaratively.

1 Like

Why not?

Because as far as I know hm does not support it.

Then it should. There must be a method to enable package-provided systemd user services.

I aggree!

How exactly did you create the override?

xdg.configfile."systemd/user/..."...

I discarded the details, as I found it does not work :frowning:

I think it’s worth debugging this as it should work.

Thanks. I tried it imperativly using:

systemctl --user edit xwayland-satellite.service

and added a Install section, which in my case is already present in the upstream service unit:

### Editing /home/xxx/.config/systemd/user/xwayland-satellite.service.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file

[Install]
WantedBy=graphical-session.target

### Edits below this comment will be discarded


### /home/xxx/.nix-profile/share/systemd/user/xwayland-satellite.service
# [Unit]
# Description=Xwayland outside your Wayland
# BindsTo=graphical-session.target
# PartOf=graphical-session.target
# After=graphical-session.target
# Requisite=graphical-session.target
# 
# [Service]
# Type=notify
# NotifyAccess=all
# ExecStart=/nix/store/zf62s4pszdwr4cg4jrsljwf4z7jp4h0k-xwayland-satellite-0.5.0-02f3054/bin/xwayland-satellite
# StandardOutput=journal
# 
# [Install]
# WantedBy=graphical-session.target

I forced systemd to re-read the definitions and checked the active status:

systemctl --user daemon-reload
systemctl --user is-enabled xwayland-satellite.service
disabled

So it claims the unit is disabled, which is somehow logical because no one enabled it. I don’t think it helps to repeat that using xdg.configFile because there again will be no one to enable the unit.

I don’t think WantedBy works as a raw systemd unit value; you need to symlink the unit into graphical-session.target.wants/. In NixOS we have machinery which does this automagically.

I agree. It was my poor trial to get a better understanding. Meanwhile I played with

systemctl --user add-requires graphical-session.target xwayland-satellite.service

which could maybe work, but it is still imperative. My latest attempt goes into the direction to create the missing wantedBy symlink with home-manager:

xdg.configFile."systemd/user/graphical-session.target.wants/xwayland-satellite.service" = {
  source = "${cfg.package}/share/systemd/user/xwayland-satellite.service";
  onChange = ''echo "Maybe run systemctl --user restart xwayland-satellite.service"'';
};

home.activation.xwayland-satellite = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
  if ! ${pkgs.systemd}/bin/systemctl --user --quiet is-active xwayland-satellite.service; then
    echo "Maybe run systemctl --user start xwayland-satellite.service"
  fi
'';

It is not perfect nor ideal, but initial testing looks promising. It is a hack but this way I can avoid to duplicate the service definition. Personally I more and more dislike home-manager for managing my personal configuration. Maybe in the future I will try to use nix profiles as an alternative approach. But lets see.

Update: With NixOS the issue can be easily solved using (maybe there is even a more elaborate way):

systemd.user.targets.graphical-session = {
    wants = [ "xwayland-satellite.service" ];
};

… assuming that the package is in users.users.<name>.packages. As a reminder: The package still provides the service unit, i.e. it is not self defined.