From 6cb0b6a4d63bab23bb5cd460561bf60b701db48b Mon Sep 17 00:00:00 2001 From: Kevin Cox Date: Wed, 28 Jun 2023 17:19:13 -0400 Subject: [PATCH] nixos.minetest-server: Add option for generating config file and ability to add extra command line flags This adds two main features: 1. `services.minetest-server.config` is an options object that is automatically serialized into a minetest config file. 2. `services.minetest-server.extraArgs` provides an escape hatch to pass extra arguments. --- .../services/games/minetest-server.nix | 71 ++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/nixos/modules/services/games/minetest-server.nix b/nixos/modules/services/games/minetest-server.nix index 578364ec542b..8dc360153497 100644 --- a/nixos/modules/services/games/minetest-server.nix +++ b/nixos/modules/services/games/minetest-server.nix @@ -3,15 +3,52 @@ with lib; let + CONTAINS_NEWLINE_RE = ".*\n.*"; + # The following values are reserved as complete option values: + # { - start of a group. + # """ - start of a multi-line string. + RESERVED_VALUE_RE = "[[:space:]]*(\"\"\"|\\{)[[:space:]]*"; + NEEDS_MULTILINE_RE = "${CONTAINS_NEWLINE_RE}|${RESERVED_VALUE_RE}"; + + # There is no way to encode """ on its own line in a Minetest config. + UNESCAPABLE_RE = ".*\n\"\"\"\n.*"; + + toConfMultiline = name: value: + assert lib.assertMsg + ((builtins.match UNESCAPABLE_RE value) == null) + ''""" can't be on its own line in a minetest config.''; + "${name} = \"\"\"\n${value}\n\"\"\"\n"; + + toConf = values: + lib.concatStrings + (lib.mapAttrsToList + (name: value: { + bool = "${name} = ${toString value}\n"; + int = "${name} = ${toString value}\n"; + null = ""; + set = "${name} = {\n${toConf value}}\n"; + string = + if (builtins.match NEEDS_MULTILINE_RE value) != null + then toConfMultiline name value + else "${name} = ${value}\n"; + }.${builtins.typeOf value}) + values); + cfg = config.services.minetest-server; - flag = val: name: optionalString (val != null) "--${name} ${toString val} "; + flag = val: name: lib.optionals (val != null) ["--${name}" "${toString val}"]; + flags = [ - (flag cfg.gameId "gameid") - (flag cfg.world "world") - (flag cfg.configPath "config") - (flag cfg.logPath "logfile") - (flag cfg.port "port") - ]; + "--server" + ] + ++ ( + if cfg.configPath != null + then ["--config" cfg.configPath] + else ["--config" (builtins.toFile "minetest.conf" (toConf cfg.config))]) + ++ (flag cfg.gameId "gameid") + ++ (flag cfg.world "world") + ++ (flag cfg.logPath "logfile") + ++ (flag cfg.port "port") + ++ cfg.extraArgs; in { options = { @@ -55,6 +92,16 @@ in ''; }; + config = mkOption { + type = types.attrsOf types.anything; + default = {}; + description = lib.mdDoc '' + Settings to add to the minetest config file. + + This option is ignored if `configPath` is set. + ''; + }; + logPath = mkOption { type = types.nullOr types.path; default = null; @@ -75,6 +122,14 @@ in If set to null, the default 30000 will be used. ''; }; + + extraArgs = mkOption { + type = types.listOf types.str; + default = []; + description = lib.mdDoc '' + Additional command line flags to pass to the minetest executable. + ''; + }; }; }; @@ -100,7 +155,7 @@ in script = '' cd /var/lib/minetest - exec ${pkgs.minetest}/bin/minetest --server ${concatStrings flags} + exec ${pkgs.minetest}/bin/minetest ${lib.escapeShellArgs flags} ''; }; };