diff --git a/modules/users/default.nix b/modules/users/default.nix index 37011a82..216dbae9 100644 --- a/modules/users/default.nix +++ b/modules/users/default.nix @@ -1,4 +1,4 @@ -{ config, lib, options, sane-lib, utils, ... }: +{ config, lib, options, sane-lib, ... }: let sane-user-cfg = config.sane.user; @@ -222,67 +222,6 @@ let done ''; } - { - fs = lib.mkMerge (lib.mapAttrsToList (serviceName: value: - let - # see: - # see: - cleanName = utils.systemdUtils.lib.mkPathSafeName serviceName; - generatedUnit = utils.systemdUtils.lib.serviceToUnit serviceName { - inherit (value) - requiredBy - script - wantedBy - ; - serviceConfig = lib.filterAttrs (_: v: v != null) value.serviceConfig; - unitConfig = { - inherit (value.unitConfig) - ConditionEnvironment - ; - After = value.after; - Before = value.before; - BindsTo = value.bindsTo; - Description = value.description; - Documentation = value.documentation; - Wants = value.wants; - }; - environment = { - # clear PATH to allow inheriting it from environment. - # otherwise, nixos would force it to `systemd.globalEnvironment.PATH`, which is mostly tools like sed/find/etc. - # clearing PATH here allows user services to inherit whatever PATH the graphical session sets - # (see `dbus-update-activation-environment` call in ~/.config/sway/config), - # which is critical to making it so user services can see user *programs*/packages. - # - # note that systemd provides no way to *append* to the PATH, only to override it (or not). - # nor do they intend to ever support that: - # - - PATH = null; - } // (value.environment or {}); - }; - #^ generatedUnit contains keys: - # - text - # - aliases (IGNORED) - # - wantedBy - # - requiredBy - # - enabled (IGNORED) - # - overrideStrategy (IGNORED) - # TODO: error if one of the above ignored fields are set - symlinkData = { - text = generatedUnit.text; - targetName = "${cleanName}.service"; # systemd derives unit name from symlink target - }; - serviceEntry = { - ".config/systemd/user/${serviceName}.service".symlink = symlinkData; - }; - wants = builtins.map (wantedBy: { - ".config/systemd/user/${wantedBy}.wants/${serviceName}.service".symlink = symlinkData; - }) generatedUnit.wantedBy; - requires = builtins.map (requiredBy: { - ".config/systemd/user/${requiredBy}.requires/${serviceName}.service".symlink = symlinkData; - }) generatedUnit.requiredBy; - in lib.mkMerge ([ serviceEntry ] ++ wants ++ requires) - ) config.services); - } ]; }); processUser = user: defn: @@ -305,6 +244,10 @@ let }; in { + imports = [ + ./systemd.nix + ]; + options = with lib; { sane.users = mkOption { type = types.attrsOf userModule; diff --git a/modules/users/systemd.nix b/modules/users/systemd.nix new file mode 100644 index 00000000..3b57669b --- /dev/null +++ b/modules/users/systemd.nix @@ -0,0 +1,76 @@ +{ lib, utils, ... }: +let + # see: + # see: + mkUnit = serviceName: value: utils.systemdUtils.lib.serviceToUnit serviceName { + inherit (value) + requiredBy + script + wantedBy + ; + serviceConfig = lib.filterAttrs (_: v: v != null) value.serviceConfig; + unitConfig = { + inherit (value.unitConfig) + ConditionEnvironment + ; + After = value.after; + Before = value.before; + BindsTo = value.bindsTo; + Description = value.description; + Documentation = value.documentation; + Wants = value.wants; + }; + environment = { + # clear PATH to allow inheriting it from environment. + # otherwise, nixos would force it to `systemd.globalEnvironment.PATH`, which is mostly tools like sed/find/etc. + # clearing PATH here allows user services to inherit whatever PATH the graphical session sets + # (see `dbus-update-activation-environment` call in ~/.config/sway/config), + # which is critical to making it so user services can see user *programs*/packages. + # + # note that systemd provides no way to *append* to the PATH, only to override it (or not). + # nor do they intend to ever support that: + # - + PATH = null; + } // (value.environment or {}); + }; +in +{ + # create fs entries for every service, in the systemd user dir. + options.sane.users = with lib; mkOption { + type = types.attrsOf (types.submodule ({ config, ...}: { + fs = lib.concatMapAttrs + (serviceName: value: let + cleanName = utils.systemdUtils.lib.mkPathSafeName serviceName; + generatedUnit = mkUnit serviceName value; + #^ generatedUnit contains keys: + # - text + # - aliases (IGNORED) + # - wantedBy + # - requiredBy + # - enabled (IGNORED) + # - overrideStrategy (IGNORED) + # TODO: error if one of the above ignored fields are set + symlinkData = { + text = generatedUnit.text; + targetName = "${cleanName}.service"; # systemd derives unit name from symlink target + }; + serviceEntry = { + ".config/systemd/user/${serviceName}.service".symlink = symlinkData; + }; + wants = builtins.map (wantedBy: { + ".config/systemd/user/${wantedBy}.wants/${serviceName}.service".symlink = symlinkData; + }) generatedUnit.wantedBy; + requires = builtins.map (requiredBy: { + ".config/systemd/user/${requiredBy}.requires/${serviceName}.service".symlink = symlinkData; + }) generatedUnit.requiredBy; + in lib.mergeAttrsList + ([ serviceEntry ] + ++ wants + ++ requires + ) + ) + config.services + ; + })); + }; +}