Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nixos/doc/manual/development/modular-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ It is possible to write service modules that are portable. This is done by eithe
{ config, options, lib, ... }: {
_class = "service";
config = {
process.executable = "${lib.getExe config.foo.program}";
process.argv = [ (lib.getExe config.foo.program) ];
} // lib.optionalAttrs (options?systemd) {
# ... systemd-specific definitions ...
};
Expand Down
27 changes: 6 additions & 21 deletions nixos/modules/system/service/portable/service.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@
let
inherit (lib) mkOption types;
pathOrStr = types.coercedTo types.path (x: "${x}") types.str;
program =
types.coercedTo (
types.package
// {
# require mainProgram for this conversion
check = v: v.type or null == "derivation" && v ? meta.mainProgram;
}
) lib.getExe pathOrStr
// {
description = "main program, path or command";
descriptionClass = "conjunction";
};
in
{
# https://nixos.org/manual/nixos/unstable/#modular-services
Expand All @@ -45,18 +33,15 @@ in
visible = "shallow";
};
process = {
executable = mkOption {
type = program;
description = ''
The path to the executable that will be run when the service is started.
'';
};
args = lib.mkOption {
argv = lib.mkOption {
type = types.listOf pathOrStr;
example = lib.literalExpression ''[ (lib.getExe config.package) "--nobackground" ]'';
description = ''
Arguments to pass to the `executable`.
Command filename and arguments for starting this service.
This is a raw command-line that should not contain any shell escaping.
If expansion of environmental variables is required then use
a shell script or `importas` from `pkgs.execline`.
'';
default = [ ];
};
};
};
Expand Down
49 changes: 31 additions & 18 deletions nixos/modules/system/service/portable/test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ let
services = {
service1 = {
process = {
executable = "/usr/bin/echo"; # *giggles*
args = [ "hello" ];
argv = [
"/usr/bin/echo" # *giggles*
"hello"
];
};
assertions = [
{
Expand All @@ -37,21 +39,27 @@ let
process = {
# No meta.mainProgram, because it's supposedly an executable script _file_,
# not a directory with a bin directory containing the main program.
executable = dummyPkg "cowsay.sh";
args = [ "world" ];
argv = [
(dummyPkg "cowsay.sh")
"world"
];
};
};
service3 = {
process = {
executable = "/bin/false";
args = [ ];
argv = [ "/bin/false" ];
};
services.exclacow = {
process = {
executable = dummyPkg "cowsay-ng" // {
meta.mainProgram = "cowsay";
};
args = [ "!" ];
argv = [
(lib.getExe (
dummyPkg "cowsay-ng"
// {
meta.mainProgram = "cowsay";
}
))
"!"
];
};
assertions = [
{
Expand Down Expand Up @@ -91,8 +99,10 @@ let
services = {
service1 = {
process = {
executable = "/usr/bin/echo";
args = [ "hello" ];
argv = [
"/usr/bin/echo"
"hello"
];
};
services = { };
assertions = [
Expand All @@ -107,22 +117,25 @@ let
};
service2 = {
process = {
executable = "${dummyPkg "cowsay.sh"}";
args = [ "world" ];
argv = [
"${dummyPkg "cowsay.sh"}"
"world"
];
};
services = { };
assertions = [ ];
warnings = [ ];
};
service3 = {
process = {
executable = "/bin/false";
args = [ ];
argv = [ "/bin/false" ];
};
services.exclacow = {
process = {
executable = "${dummyPkg "cowsay-ng"}/bin/cowsay";
args = [ "!" ];
argv = [
"${dummyPkg "cowsay-ng"}/bin/cowsay"
"!"
];
};
services = { };
assertions = [
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/system/service/systemd/service.nix
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ in
Restart = lib.mkDefault "always";
RestartSec = lib.mkDefault "5";
ExecStart = [
(systemdPackage.functions.escapeSystemdExecArgs ([ config.process.executable ] ++ config.process.args))
(systemdPackage.functions.escapeSystemdExecArgs config.process.argv)
];
};
};
Expand Down
21 changes: 12 additions & 9 deletions nixos/modules/system/service/systemd/test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,26 @@
let
machine = evalSystem (
{ lib, ... }:
let
hello' = lib.getExe hello;
in
{

# Test input

system.services.foo = {
process = {
executable = hello;
args = [
argv = [
hello'
"--greeting"
"hoi"
];
};
};
system.services.bar = {
process = {
executable = hello;
args = [
argv = [
hello'
"--greeting"
"hoi"
];
Expand All @@ -37,8 +40,8 @@ let
};
services.db = {
process = {
executable = hello;
args = [
argv = [
hello'
"--greeting"
"Hi, I'm a database, would you believe it"
];
Expand Down Expand Up @@ -72,12 +75,12 @@ runCommand "test-modular-service-systemd-units"
cat -n ${toplevel}/etc/systemd/system/foo.service
(
set -x
grep -F 'ExecStart=${hello}/bin/hello --greeting hoi' ${toplevel}/etc/systemd/system/foo.service >/dev/null
grep -F 'ExecStart="${hello}/bin/hello" "--greeting" "hoi"' ${toplevel}/etc/systemd/system/foo.service >/dev/null

grep -F 'ExecStart=${hello}/bin/hello --greeting hoi' ${toplevel}/etc/systemd/system/bar.service >/dev/null
grep -F 'ExecStart="${hello}/bin/hello" "--greeting" "hoi"' ${toplevel}/etc/systemd/system/bar.service >/dev/null
grep -F 'X-Bar=lol crossbar whatever' ${toplevel}/etc/systemd/system/bar.service >/dev/null

grep 'ExecStart=${hello}/bin/hello --greeting .*database.*' ${toplevel}/etc/systemd/system/bar-db.service >/dev/null
grep 'ExecStart="${hello}/bin/hello" "--greeting" ".*database.*"' ${toplevel}/etc/systemd/system/bar-db.service >/dev/null
grep -F 'RestartSec=42' ${toplevel}/etc/systemd/system/bar-db.service >/dev/null

[[ ! -e ${toplevel}/etc/systemd/system/foo.socket ]]
Expand Down
69 changes: 41 additions & 28 deletions pkgs/by-name/gh/ghostunnel/service.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ let
inherit (lib)
concatStringsSep
escapeShellArg
getExe
mkDefault
mkIf
mkOption
Expand Down Expand Up @@ -130,9 +131,9 @@ in
};

extraArguments = mkOption {
description = "Extra arguments to pass to `ghostunnel server` (shell syntax)";
type = types.separatedString " ";
default = "";
description = "Extra arguments to pass to `ghostunnel server`";
type = types.listOf types.str;
default = [ ];
};

unsafeTarget = mkOption {
Expand Down Expand Up @@ -181,32 +182,44 @@ in
# TODO assertions

process = {
executable = pkgs.writeScriptBin "run-ghostunnel" ''
#!${pkgs.runtimeShell}
exec ${lib.getExe cfg.package} ${
concatStringsSep " " (
optional (cfg.keystore != null) "--keystore=$CREDENTIALS_DIRECTORY/keystore"
++ optional (cfg.cert != null) "--cert=$CREDENTIALS_DIRECTORY/cert"
++ optional (cfg.key != null) "--key=$CREDENTIALS_DIRECTORY/key"
++ optional (cfg.cacert != null) "--cacert=$CREDENTIALS_DIRECTORY/cacert"
++ [
"server"
"--listen"
cfg.listen
"--target"
cfg.target
]
++ optional cfg.allowAll "--allow-all"
++ map (v: "--allow-cn=${escapeShellArg v}") cfg.allowCN
++ map (v: "--allow-ou=${escapeShellArg v}") cfg.allowOU
++ map (v: "--allow-dns=${escapeShellArg v}") cfg.allowDNS
++ map (v: "--allow-uri=${escapeShellArg v}") cfg.allowURI
++ optional cfg.disableAuthentication "--disable-authentication"
++ optional cfg.unsafeTarget "--unsafe-target"
++ [ cfg.extraArguments ]
argv =
# Use a shell if credentials need to be pulled from the environment.
optional
(builtins.any (v: v != null) [
cfg.keystore
cfg.cert
cfg.key
cfg.cacert
])
(
pkgs.writeScript "load-credentials" ''
#!${pkgs.runtimeShell}
exec $@ ${
concatStringsSep " " (
optional (cfg.keystore != null) "--keystore=$CREDENTIALS_DIRECTORY/keystore"
++ optional (cfg.cert != null) "--cert=$CREDENTIALS_DIRECTORY/cert"
++ optional (cfg.key != null) "--key=$CREDENTIALS_DIRECTORY/key"
++ optional (cfg.cacert != null) "--cacert=$CREDENTIALS_DIRECTORY/cacert"
)
}
''
)
}
'';
++ [
(getExe cfg.package)
"server"
"--listen"
cfg.listen
"--target"
cfg.target
]
++ optional cfg.allowAll "--allow-all"
++ map (v: "--allow-cn=${v}") cfg.allowCN
++ map (v: "--allow-ou=${v}") cfg.allowOU
++ map (v: "--allow-dns=${v}") cfg.allowDNS
++ map (v: "--allow-uri=${v}") cfg.allowURI
++ optional cfg.disableAuthentication "--disable-authentication"
++ optional cfg.unsafeTarget "--unsafe-target"
++ cfg.extraArguments;
};

# refine the service
Expand Down
Loading