How to enable upstream systemd user services declaratively?

I’ve found myself confused by user services in NixOS, so I want to share what I have learned:

User unit files are installed in /etc/systemd/user/. This is kind of like a “library” of available user services on the system. You can add the user units from packages into the installed set with the systemd.packages option:

{
  systemd.packages = with pkgs; [ ydotool ];
}

User services typically have an [Install] section which is essentially a set of instructions for what to symlink in .config/systemd/user when systemctl --user enable <service>. For example, from ydotool.service:

[Install]
WantedBy=default.target

If you enable the service, this creates a symlink .config/systemd/user/default.target.wants/ydotool.service -> /etc/systemd/user/ydotool.service. NixOS doesn’t look at the [Install] section, so you might think (as I did) that you have to run systemctl --user enable yourself for every service, or create the relevant symlinks yourself.

That’s (thankfully) not true! You can declare the contents of the [Install] section in your NixOS configuration:

{
  systemd.packages = [ pkgs.ydotool ];
  systemd.user.services.ydotool.wantedBy = [ "default.target" ];
}

No manual symlinks or enable steps are needed. This adds symlinks to the default.target.wants directory in /etc/systemd/user. So, more than being a “library” of user units, it’s also a “base configuration” of user units for all users.

3 Likes