modules/programs: enforce (or rather document) a stricter schema
this should make it easier to switch to a different service manager
This commit is contained in:
parent
1b4a6207e2
commit
c8e5edd61a
|
@ -255,18 +255,12 @@ let
|
|||
'';
|
||||
};
|
||||
services = mkOption {
|
||||
# see: <repo:nixos/nixpkgs:nixos/lib/utils.nix>
|
||||
# type = utils.systemdUtils.types.services;
|
||||
# map to listOf attrs so that we can allow multiple assigners to the same service
|
||||
# w/o worrying about merging at this layer, and defer merging to modules/users instead.
|
||||
type = types.attrsOf (types.coercedTo types.attrs (a: [ a ]) (types.listOf types.attrs));
|
||||
type = types.attrsOf types.anything; # options.sane.users.value.type;
|
||||
default = {};
|
||||
description = ''
|
||||
systemd services to define if this package is enabled.
|
||||
currently only defines USER services -- acts as noop for root-enabled packages.
|
||||
|
||||
conventions are similar to `systemd.services` or `sane.users.<user>.services`.
|
||||
the type at this level is obscured only to as to allow passthrough to `sane.users` w/ proper option merging
|
||||
user services to define if this package is enabled.
|
||||
acts as noop for root-enabled packages.
|
||||
see `sane.users.<user>.services` for options;
|
||||
'';
|
||||
};
|
||||
slowToBuild = mkOption {
|
||||
|
@ -542,8 +536,7 @@ let
|
|||
|
||||
# conditionally persist relevant user dirs and create files
|
||||
sane.users = lib.mapAttrs (user: en: lib.optionalAttrs (en && p.enabled) {
|
||||
inherit (p) persist;
|
||||
services = lib.mapAttrs (_: lib.mkMerge) p.services;
|
||||
inherit (p) persist services;
|
||||
environment = p.env;
|
||||
fs = lib.mkMerge [
|
||||
p.fs
|
||||
|
|
|
@ -4,6 +4,102 @@ let
|
|||
sane-user-cfg = config.sane.user;
|
||||
cfg = config.sane.users;
|
||||
path-lib = sane-lib.path;
|
||||
serviceType = with lib; types.submodule {
|
||||
options = {
|
||||
# these aoptions are mostly copied from systemd. could be improved.
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
documentation = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
references and links for where to find documentation about this service.
|
||||
'';
|
||||
};
|
||||
after = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
bindsTo = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
before = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
requiredBy = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
wantedBy = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
wants = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
script = mkOption {
|
||||
type = types.nullOr types.lines;
|
||||
default = null;
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
environment variables to set within the service.
|
||||
'';
|
||||
};
|
||||
|
||||
serviceConfig.Type = mkOption {
|
||||
type = types.enum [ "dbus" "oneshot" "simple" ];
|
||||
};
|
||||
serviceConfig.ExecStart = mkOption {
|
||||
type = types.nullOr (types.coercedTo types.package toString types.str);
|
||||
default = null;
|
||||
};
|
||||
serviceConfig.ExecStartPre = mkOption {
|
||||
type = types.nullOr (types.coercedTo types.package toString types.str);
|
||||
default = null;
|
||||
};
|
||||
serviceConfig.ExecStartPost = mkOption {
|
||||
type = types.nullOr (types.coercedTo types.package toString types.str);
|
||||
default = null;
|
||||
};
|
||||
serviceConfig.ExecStopPost = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
serviceConfig.BusName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
name of the dbus name this service is expected to register.
|
||||
only once the name is registered will the service be considered "active".
|
||||
'';
|
||||
};
|
||||
serviceConfig.RemainAfterExit = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
serviceConfig.Restart = mkOption {
|
||||
type = types.nullOr (types.enum [ "always" "on-failure" ]);
|
||||
default = null;
|
||||
# N.B.: systemd doesn't allow always/on-failure for Type="oneshot" services
|
||||
};
|
||||
serviceConfig.RestartSec = mkOption {
|
||||
type = types.str;
|
||||
default = "20s";
|
||||
};
|
||||
unitConfig.ConditionEnvironment = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
userOptions = {
|
||||
options = with lib; {
|
||||
fs = mkOption {
|
||||
|
@ -48,10 +144,10 @@ let
|
|||
# type = utils.systemdUtils.types.services;
|
||||
# `utils.systemdUtils.types.services` is nearly what we want, but remove `stage2ServiceConfig`,
|
||||
# as we don't want to force a PATH for every service.
|
||||
type = types.attrsOf (types.submodule [ utils.systemdUtils.unitOptions.stage2ServiceOptions utils.systemdUtils.lib.unitConfig ]);
|
||||
type = types.attrsOf serviceType;
|
||||
default = {};
|
||||
description = ''
|
||||
systemd user-services to define for this user.
|
||||
services to define for this user.
|
||||
populates files in ~/.config/systemd.
|
||||
'';
|
||||
};
|
||||
|
@ -132,8 +228,25 @@ let
|
|||
# see: <repo:nixos/nixpkgs:nixos/lib/utils.nix>
|
||||
# see: <repo:nix-community/home-manager:modules/systemd.nix>
|
||||
cleanName = utils.systemdUtils.lib.mkPathSafeName serviceName;
|
||||
generatedUnit = utils.systemdUtils.lib.serviceToUnit serviceName (value // {
|
||||
environment = lib.throwIf (value.path != []) "user service ${serviceName} specifies unsupported 'path' attribute (${builtins.toString value.path})" {
|
||||
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
|
||||
|
@ -145,7 +258,7 @@ let
|
|||
# - <https://github.com/systemd/systemd/issues/1082>
|
||||
PATH = null;
|
||||
} // (value.environment or {});
|
||||
});
|
||||
};
|
||||
#^ generatedUnit contains keys:
|
||||
# - text
|
||||
# - aliases (IGNORED)
|
||||
|
|
Loading…
Reference in New Issue