How to enable upstream systemd user services declaratively?

OK so this is a bit emberrasing, as I’m using NixOS for more then a year and only now I’ve stopped to think that maybe my current usage of systemd services is not good.

So basically, if I run systemctl --user enable <this> I can enable user systemd services provided by packages. This creates a symlinks such as:

lrwxrwxrwx 1 doron developers 95 Jun 12 13:31 default.target.wants/pulseaudio.service -> /nix/store/j9sg853np8czrvdsfg6qdbmn599h3370-pulseaudio-13.0/lib/systemd/user/pulseaudio.service
lrwxrwxrwx 1 doron developers 95 Jun 12 13:31 pulseaudio.service -> /nix/store/j9sg853np8czrvdsfg6qdbmn599h3370-pulseaudio-13.0/lib/systemd/user/pulseaudio.service

But as you can see, the symlinks are absolute, meaning that nix-collect-garbage -d might remove kill the symlinks and then I’ll have to run systemctl --user reenable pulseaudio, not to mention the fact that the service that the symlink targets to, probably points in ExecStart= to the binary of the old pulseaudio…

The workaround I thought of was a script that will run systemctl --user reenable for every service I enable. And I have to run this script after every time I collect garbage.

But that’s absurd right? I could create the symlinks by myself and point them to /run/current-system/ but that means I’m not enjoying systemctl. Is it possible to use the system’s configuration.nix to do declaratively do it? Or perhaps there’s a nicer way to handle these symlinks?

I’d like to avoid using home-manager because it’s features are too bloat for me.

pulseaudio in particular has a NixOS module which you can simply enable to have the user service running. Others may have something similar.

I’m aware of this module. Though I noticed that I have to systemctl start pulseaudio in order for pulseaudio to actually run. Perhaps your experience is different, possibly due to a different xorg related settings or DE specific behavior.

That’s weird. Unless something modifies the service configuration from the side, it should just start for each user according to the source. Which release are you on?

Hmm now I tested and it seems you are correct, perhaps this was a false conclusion - that I need to enable the services by myself explicitly.

I guess the solution then is to put in my configuration.nix exactly what these services do when I enable them.

However, what I’m still unsure of, is whether service files given by upstream packages are playing along with systemd.user.services - I mean, what do I need to do if I want to enable for all users a systemd service provided by a certain package? Without any changes to it? Is systemd.packages = [ pkgs.<myPkg> ]; supposed to be enough?

I think that the answer is yes according to:

But it doesn’t seem documented in the docs of systemd.packages?

Not the prettiest approach, nor is it declarative as you requested, but it Works For Me™ (and is independent of the system configuration): I manually symlinked service definitions from .nix-profile:

$ ls -l .config/systemd/user/syncthing.service
lrwxrwxrwx 1 linus users 56 Oct  7  2018 .config/systemd/user/syncthing.service -> ../../../.nix-profile/lib/systemd/user/syncthing.service

(as you can see, I’ve been running on this approach for a little while now)

And only then running systemctl --user daemon-reload and systemctl --user enable syncthing.service.

This is the approach I’m testing right now. It seems to be good enough at the moment, so thanks for explaining it. It should be possible though, to replicate what e.g pulseaudio’s module does in declaratively. I noted my self to investigate it and document this in the manual.

1 Like