systemd: add a name option to all systemd units
This allows us to set things like dependencies in a way that we can catch typos at eval time. So instead of ```nix systemd.services.foo.wants = [ "bar.service" ]; ``` we can write ```nix systemd.services.foo.wants = [ config.systemd.services.bar.name ]; ``` which will throw an error if no such service has been defined. Not all cases can be done like this (eg template services), but in a lot of cases this will allow to avoid typos. There is a matching option on the unit option (`systemd.units."foo.service".name`) as well.
This commit is contained in:
parent
b432281d97
commit
9258f57625
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, pkgs }:
|
{ config, lib, pkgs, utils }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
@ -381,8 +381,41 @@ in rec {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
serviceConfig = { config, ... }: {
|
serviceConfig = { name, config, ... }: {
|
||||||
config.environment.PATH = mkIf (config.path != []) "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
|
config = {
|
||||||
|
name = "${name}.service";
|
||||||
|
environment.PATH = mkIf (config.path != []) "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pathConfig = { name, config, ... }: {
|
||||||
|
config = {
|
||||||
|
name = "${name}.path";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
socketConfig = { name, config, ... }: {
|
||||||
|
config = {
|
||||||
|
name = "${name}.socket";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sliceConfig = { name, config, ... }: {
|
||||||
|
config = {
|
||||||
|
name = "${name}.slice";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
targetConfig = { name, config, ... }: {
|
||||||
|
config = {
|
||||||
|
name = "${name}.target";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
timerConfig = { name, config, ... }: {
|
||||||
|
config = {
|
||||||
|
name = "${name}.timer";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
stage2ServiceConfig = {
|
stage2ServiceConfig = {
|
||||||
|
@ -401,6 +434,7 @@ in rec {
|
||||||
|
|
||||||
mountConfig = { config, ... }: {
|
mountConfig = { config, ... }: {
|
||||||
config = {
|
config = {
|
||||||
|
name = "${utils.escapeSystemdPath config.where}.mount";
|
||||||
mountConfig =
|
mountConfig =
|
||||||
{ What = config.what;
|
{ What = config.what;
|
||||||
Where = config.where;
|
Where = config.where;
|
||||||
|
@ -414,6 +448,7 @@ in rec {
|
||||||
|
|
||||||
automountConfig = { config, ... }: {
|
automountConfig = { config, ... }: {
|
||||||
config = {
|
config = {
|
||||||
|
name = "${utils.escapeSystemdPath config.where}.automount";
|
||||||
automountConfig =
|
automountConfig =
|
||||||
{ Where = config.where;
|
{ Where = config.where;
|
||||||
};
|
};
|
||||||
|
@ -429,8 +464,8 @@ in rec {
|
||||||
WantedBy=${concatStringsSep " " def.wantedBy}
|
WantedBy=${concatStringsSep " " def.wantedBy}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
targetToUnit = name: def:
|
targetToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text =
|
text =
|
||||||
''
|
''
|
||||||
[Unit]
|
[Unit]
|
||||||
|
@ -438,8 +473,8 @@ in rec {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
serviceToUnit = name: def:
|
serviceToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text = commonUnitText def (''
|
text = commonUnitText def (''
|
||||||
[Service]
|
[Service]
|
||||||
'' + (let env = cfg.globalEnvironment // def.environment;
|
'' + (let env = cfg.globalEnvironment // def.environment;
|
||||||
|
@ -448,7 +483,7 @@ in rec {
|
||||||
"Environment=${toJSON "${n}=${env.${n}}"}\n";
|
"Environment=${toJSON "${n}=${env.${n}}"}\n";
|
||||||
# systemd max line length is now 1MiB
|
# systemd max line length is now 1MiB
|
||||||
# https://github.com/systemd/systemd/commit/e6dde451a51dc5aaa7f4d98d39b8fe735f73d2af
|
# https://github.com/systemd/systemd/commit/e6dde451a51dc5aaa7f4d98d39b8fe735f73d2af
|
||||||
in if stringLength s >= 1048576 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${name}.service’ is too long." else s) (attrNames env))
|
in if stringLength s >= 1048576 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${def.name}.service’ is too long." else s) (attrNames env))
|
||||||
+ (if def ? reloadIfChanged && def.reloadIfChanged then ''
|
+ (if def ? reloadIfChanged && def.reloadIfChanged then ''
|
||||||
X-ReloadIfChanged=true
|
X-ReloadIfChanged=true
|
||||||
'' else if (def ? restartIfChanged && !def.restartIfChanged) then ''
|
'' else if (def ? restartIfChanged && !def.restartIfChanged) then ''
|
||||||
|
@ -459,8 +494,8 @@ in rec {
|
||||||
'' + attrsToSection def.serviceConfig);
|
'' + attrsToSection def.serviceConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
socketToUnit = name: def:
|
socketToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text = commonUnitText def ''
|
text = commonUnitText def ''
|
||||||
[Socket]
|
[Socket]
|
||||||
${attrsToSection def.socketConfig}
|
${attrsToSection def.socketConfig}
|
||||||
|
@ -469,40 +504,40 @@ in rec {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
timerToUnit = name: def:
|
timerToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text = commonUnitText def ''
|
text = commonUnitText def ''
|
||||||
[Timer]
|
[Timer]
|
||||||
${attrsToSection def.timerConfig}
|
${attrsToSection def.timerConfig}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
pathToUnit = name: def:
|
pathToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text = commonUnitText def ''
|
text = commonUnitText def ''
|
||||||
[Path]
|
[Path]
|
||||||
${attrsToSection def.pathConfig}
|
${attrsToSection def.pathConfig}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
mountToUnit = name: def:
|
mountToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text = commonUnitText def ''
|
text = commonUnitText def ''
|
||||||
[Mount]
|
[Mount]
|
||||||
${attrsToSection def.mountConfig}
|
${attrsToSection def.mountConfig}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
automountToUnit = name: def:
|
automountToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text = commonUnitText def ''
|
text = commonUnitText def ''
|
||||||
[Automount]
|
[Automount]
|
||||||
${attrsToSection def.automountConfig}
|
${attrsToSection def.automountConfig}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
sliceToUnit = name: def:
|
sliceToUnit = def:
|
||||||
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
{ inherit (def) name aliases wantedBy requiredBy upheldBy enable overrideStrategy;
|
||||||
text = commonUnitText def ''
|
text = commonUnitText def ''
|
||||||
[Slice]
|
[Slice]
|
||||||
${attrsToSection def.sliceConfig}
|
${attrsToSection def.sliceConfig}
|
||||||
|
|
|
@ -5,8 +5,13 @@ let
|
||||||
automountConfig
|
automountConfig
|
||||||
makeUnit
|
makeUnit
|
||||||
mountConfig
|
mountConfig
|
||||||
|
pathConfig
|
||||||
|
sliceConfig
|
||||||
|
socketConfig
|
||||||
stage1ServiceConfig
|
stage1ServiceConfig
|
||||||
stage2ServiceConfig
|
stage2ServiceConfig
|
||||||
|
targetConfig
|
||||||
|
timerConfig
|
||||||
unitConfig
|
unitConfig
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -48,29 +53,32 @@ let
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
|
|
||||||
rec {
|
{
|
||||||
units = attrsOf (submodule ({ name, config, ... }: {
|
units = attrsOf (submodule ({ name, config, ... }: {
|
||||||
options = concreteUnitOptions;
|
options = concreteUnitOptions;
|
||||||
config = { unit = mkDefault (makeUnit name config); };
|
config = {
|
||||||
|
name = mkDefault name;
|
||||||
|
unit = mkDefault (makeUnit name config);
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
services = attrsOf (submodule [ stage2ServiceOptions unitConfig stage2ServiceConfig ]);
|
services = attrsOf (submodule [ stage2ServiceOptions unitConfig stage2ServiceConfig ]);
|
||||||
initrdServices = attrsOf (submodule [ stage1ServiceOptions unitConfig stage1ServiceConfig ]);
|
initrdServices = attrsOf (submodule [ stage1ServiceOptions unitConfig stage1ServiceConfig ]);
|
||||||
|
|
||||||
targets = attrsOf (submodule [ stage2CommonUnitOptions unitConfig ]);
|
targets = attrsOf (submodule [ stage2CommonUnitOptions unitConfig targetConfig ]);
|
||||||
initrdTargets = attrsOf (submodule [ stage1CommonUnitOptions unitConfig ]);
|
initrdTargets = attrsOf (submodule [ stage1CommonUnitOptions unitConfig targetConfig ]);
|
||||||
|
|
||||||
sockets = attrsOf (submodule [ stage2SocketOptions unitConfig ]);
|
sockets = attrsOf (submodule [ stage2SocketOptions unitConfig socketConfig]);
|
||||||
initrdSockets = attrsOf (submodule [ stage1SocketOptions unitConfig ]);
|
initrdSockets = attrsOf (submodule [ stage1SocketOptions unitConfig socketConfig ]);
|
||||||
|
|
||||||
timers = attrsOf (submodule [ stage2TimerOptions unitConfig ]);
|
timers = attrsOf (submodule [ stage2TimerOptions unitConfig timerConfig ]);
|
||||||
initrdTimers = attrsOf (submodule [ stage1TimerOptions unitConfig ]);
|
initrdTimers = attrsOf (submodule [ stage1TimerOptions unitConfig timerConfig ]);
|
||||||
|
|
||||||
paths = attrsOf (submodule [ stage2PathOptions unitConfig ]);
|
paths = attrsOf (submodule [ stage2PathOptions unitConfig pathConfig ]);
|
||||||
initrdPaths = attrsOf (submodule [ stage1PathOptions unitConfig ]);
|
initrdPaths = attrsOf (submodule [ stage1PathOptions unitConfig pathConfig ]);
|
||||||
|
|
||||||
slices = attrsOf (submodule [ stage2SliceOptions unitConfig ]);
|
slices = attrsOf (submodule [ stage2SliceOptions unitConfig sliceConfig ]);
|
||||||
initrdSlices = attrsOf (submodule [ stage1SliceOptions unitConfig ]);
|
initrdSlices = attrsOf (submodule [ stage1SliceOptions unitConfig sliceConfig ]);
|
||||||
|
|
||||||
mounts = listOf (submodule [ stage2MountOptions unitConfig mountConfig ]);
|
mounts = listOf (submodule [ stage2MountOptions unitConfig mountConfig ]);
|
||||||
initrdMounts = listOf (submodule [ stage1MountOptions unitConfig mountConfig ]);
|
initrdMounts = listOf (submodule [ stage1MountOptions unitConfig mountConfig ]);
|
||||||
|
|
|
@ -65,6 +65,14 @@ in rec {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
The name of this systemd unit, including its extension.
|
||||||
|
This can be used to refer to this unit from other systemd units.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
overrideStrategy = mkOption {
|
overrideStrategy = mkOption {
|
||||||
default = "asDropinIfExists";
|
default = "asDropinIfExists";
|
||||||
type = types.enum [ "asDropinIfExists" "asDropin" ];
|
type = types.enum [ "asDropinIfExists" "asDropin" ];
|
||||||
|
|
|
@ -35,7 +35,8 @@ let
|
||||||
inherit (lib.strings) toJSON normalizePath escapeC;
|
inherit (lib.strings) toJSON normalizePath escapeC;
|
||||||
in
|
in
|
||||||
|
|
||||||
rec {
|
let
|
||||||
|
utils = rec {
|
||||||
|
|
||||||
# Copy configuration files to avoid having the entire sources in the system closure
|
# Copy configuration files to avoid having the entire sources in the system closure
|
||||||
copyFile = filePath: pkgs.runCommand (builtins.unsafeDiscardStringContext (baseNameOf filePath)) {} ''
|
copyFile = filePath: pkgs.runCommand (builtins.unsafeDiscardStringContext (baseNameOf filePath)) {} ''
|
||||||
|
@ -262,11 +263,12 @@ rec {
|
||||||
filter (x: !(elem (getName x) namesToRemove)) packages;
|
filter (x: !(elem (getName x) namesToRemove)) packages;
|
||||||
|
|
||||||
systemdUtils = {
|
systemdUtils = {
|
||||||
lib = import ./systemd-lib.nix { inherit lib config pkgs; };
|
lib = import ./systemd-lib.nix { inherit lib config pkgs utils; };
|
||||||
unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
|
unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
|
||||||
types = import ./systemd-types.nix { inherit lib systemdUtils pkgs; };
|
types = import ./systemd-types.nix { inherit lib systemdUtils pkgs; };
|
||||||
network = {
|
network = {
|
||||||
units = import ./systemd-network-units.nix { inherit lib systemdUtils; };
|
units = import ./systemd-network-units.nix { inherit lib systemdUtils; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
in utils
|
||||||
|
|
|
@ -595,18 +595,17 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.units =
|
systemd.units =
|
||||||
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
|
let
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
|
withName = cfgToUnit: cfg: lib.nameValuePair cfg.name (cfgToUnit cfg);
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit n v)) cfg.slices
|
in
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.sockets
|
mapAttrs' (_: withName pathToUnit) cfg.paths
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
|
// mapAttrs' (_: withName serviceToUnit) cfg.services
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.timers
|
// mapAttrs' (_: withName sliceToUnit) cfg.slices
|
||||||
// listToAttrs (map
|
// mapAttrs' (_: withName socketToUnit) cfg.sockets
|
||||||
(v: let n = escapeSystemdPath v.where;
|
// mapAttrs' (_: withName targetToUnit) cfg.targets
|
||||||
in nameValuePair "${n}.mount" (mountToUnit n v)) cfg.mounts)
|
// mapAttrs' (_: withName timerToUnit) cfg.timers
|
||||||
// listToAttrs (map
|
// listToAttrs (map (withName mountToUnit) cfg.mounts)
|
||||||
(v: let n = escapeSystemdPath v.where;
|
// listToAttrs (map (withName automountToUnit) cfg.automounts);
|
||||||
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
|
|
||||||
|
|
||||||
# Environment of PID 1
|
# Environment of PID 1
|
||||||
systemd.managerEnvironment = {
|
systemd.managerEnvironment = {
|
||||||
|
|
|
@ -490,18 +490,18 @@ in {
|
||||||
|
|
||||||
targets.initrd.aliases = ["default.target"];
|
targets.initrd.aliases = ["default.target"];
|
||||||
units =
|
units =
|
||||||
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
|
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit v)) cfg.paths
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
|
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit v)) cfg.services
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit n v)) cfg.slices
|
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit v)) cfg.slices
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.sockets
|
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit v)) cfg.sockets
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
|
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit v)) cfg.targets
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.timers
|
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit v)) cfg.timers
|
||||||
// listToAttrs (map
|
// listToAttrs (map
|
||||||
(v: let n = escapeSystemdPath v.where;
|
(v: let n = escapeSystemdPath v.where;
|
||||||
in nameValuePair "${n}.mount" (mountToUnit n v)) cfg.mounts)
|
in nameValuePair "${n}.mount" (mountToUnit v)) cfg.mounts)
|
||||||
// listToAttrs (map
|
// listToAttrs (map
|
||||||
(v: let n = escapeSystemdPath v.where;
|
(v: let n = escapeSystemdPath v.where;
|
||||||
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
|
in nameValuePair "${n}.automount" (automountToUnit v)) cfg.automounts);
|
||||||
|
|
||||||
# make sure all the /dev nodes are set up
|
# make sure all the /dev nodes are set up
|
||||||
services.systemd-tmpfiles-setup-dev.wantedBy = ["sysinit.target"];
|
services.systemd-tmpfiles-setup-dev.wantedBy = ["sysinit.target"];
|
||||||
|
|
|
@ -175,12 +175,12 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.user.units =
|
systemd.user.units =
|
||||||
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
|
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit v)) cfg.paths
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
|
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit v)) cfg.services
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit n v)) cfg.slices
|
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit v)) cfg.slices
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.sockets
|
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit v)) cfg.sockets
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
|
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit v)) cfg.targets
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.timers;
|
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit v)) cfg.timers;
|
||||||
|
|
||||||
# Generate timer units for all services that have a ‘startAt’ value.
|
# Generate timer units for all services that have a ‘startAt’ value.
|
||||||
systemd.user.timers =
|
systemd.user.timers =
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import ./make-test-python.nix ({ pkgs, ... }: {
|
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||||
name = "systemd";
|
name = "systemd";
|
||||||
|
|
||||||
nodes.machine = { lib, ... }: {
|
nodes.machine = { config, lib, ... }: {
|
||||||
imports = [ common/user-account.nix common/x11.nix ];
|
imports = [ common/user-account.nix common/x11.nix ];
|
||||||
|
|
||||||
virtualisation.emptyDiskImages = [ 512 512 ];
|
virtualisation.emptyDiskImages = [ 512 512 ];
|
||||||
|
@ -38,9 +38,18 @@ import ./make-test-python.nix ({ pkgs, ... }: {
|
||||||
script = "true";
|
script = "true";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services.testDependency1 = {
|
||||||
|
description = "Test Dependency 1";
|
||||||
|
wantedBy = [ config.systemd.services."testservice1".name ];
|
||||||
|
serviceConfig.Type = "oneshot";
|
||||||
|
script = ''
|
||||||
|
true
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.testservice1 = {
|
systemd.services.testservice1 = {
|
||||||
description = "Test Service 1";
|
description = "Test Service 1";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ config.systemd.targets.multi-user.name ];
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
script = ''
|
script = ''
|
||||||
if [ "$XXX_SYSTEM" = foo ]; then
|
if [ "$XXX_SYSTEM" = foo ]; then
|
||||||
|
|
Loading…
Reference in New Issue
Block a user