at 23.11-beta 4.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 CONTAINS_NEWLINE_RE = ".*\n.*"; 7 # The following values are reserved as complete option values: 8 # { - start of a group. 9 # """ - start of a multi-line string. 10 RESERVED_VALUE_RE = "[[:space:]]*(\"\"\"|\\{)[[:space:]]*"; 11 NEEDS_MULTILINE_RE = "${CONTAINS_NEWLINE_RE}|${RESERVED_VALUE_RE}"; 12 13 # There is no way to encode """ on its own line in a Minetest config. 14 UNESCAPABLE_RE = ".*\n\"\"\"\n.*"; 15 16 toConfMultiline = name: value: 17 assert lib.assertMsg 18 ((builtins.match UNESCAPABLE_RE value) == null) 19 ''""" can't be on its own line in a minetest config.''; 20 "${name} = \"\"\"\n${value}\n\"\"\"\n"; 21 22 toConf = values: 23 lib.concatStrings 24 (lib.mapAttrsToList 25 (name: value: { 26 bool = "${name} = ${toString value}\n"; 27 int = "${name} = ${toString value}\n"; 28 null = ""; 29 set = "${name} = {\n${toConf value}}\n"; 30 string = 31 if (builtins.match NEEDS_MULTILINE_RE value) != null 32 then toConfMultiline name value 33 else "${name} = ${value}\n"; 34 }.${builtins.typeOf value}) 35 values); 36 37 cfg = config.services.minetest-server; 38 flag = val: name: lib.optionals (val != null) ["--${name}" "${toString val}"]; 39 40 flags = [ 41 "--server" 42 ] 43 ++ ( 44 if cfg.configPath != null 45 then ["--config" cfg.configPath] 46 else ["--config" (builtins.toFile "minetest.conf" (toConf cfg.config))]) 47 ++ (flag cfg.gameId "gameid") 48 ++ (flag cfg.world "world") 49 ++ (flag cfg.logPath "logfile") 50 ++ (flag cfg.port "port") 51 ++ cfg.extraArgs; 52in 53{ 54 options = { 55 services.minetest-server = { 56 enable = mkOption { 57 type = types.bool; 58 default = false; 59 description = lib.mdDoc "If enabled, starts a Minetest Server."; 60 }; 61 62 gameId = mkOption { 63 type = types.nullOr types.str; 64 default = null; 65 description = lib.mdDoc '' 66 Id of the game to use. To list available games run 67 `minetestserver --gameid list`. 68 69 If only one game exists, this option can be null. 70 ''; 71 }; 72 73 world = mkOption { 74 type = types.nullOr types.path; 75 default = null; 76 description = lib.mdDoc '' 77 Name of the world to use. To list available worlds run 78 `minetestserver --world list`. 79 80 If only one world exists, this option can be null. 81 ''; 82 }; 83 84 configPath = mkOption { 85 type = types.nullOr types.path; 86 default = null; 87 description = lib.mdDoc '' 88 Path to the config to use. 89 90 If set to null, the config of the running user will be used: 91 `~/.minetest/minetest.conf`. 92 ''; 93 }; 94 95 config = mkOption { 96 type = types.attrsOf types.anything; 97 default = {}; 98 description = lib.mdDoc '' 99 Settings to add to the minetest config file. 100 101 This option is ignored if `configPath` is set. 102 ''; 103 }; 104 105 logPath = mkOption { 106 type = types.nullOr types.path; 107 default = null; 108 description = lib.mdDoc '' 109 Path to logfile for logging. 110 111 If set to null, logging will be output to stdout which means 112 all output will be caught by systemd. 113 ''; 114 }; 115 116 port = mkOption { 117 type = types.nullOr types.int; 118 default = null; 119 description = lib.mdDoc '' 120 Port number to bind to. 121 122 If set to null, the default 30000 will be used. 123 ''; 124 }; 125 126 extraArgs = mkOption { 127 type = types.listOf types.str; 128 default = []; 129 description = lib.mdDoc '' 130 Additional command line flags to pass to the minetest executable. 131 ''; 132 }; 133 }; 134 }; 135 136 config = mkIf cfg.enable { 137 users.users.minetest = { 138 description = "Minetest Server Service user"; 139 home = "/var/lib/minetest"; 140 createHome = true; 141 uid = config.ids.uids.minetest; 142 group = "minetest"; 143 }; 144 users.groups.minetest.gid = config.ids.gids.minetest; 145 146 systemd.services.minetest-server = { 147 description = "Minetest Server Service"; 148 wantedBy = [ "multi-user.target" ]; 149 after = [ "network.target" ]; 150 151 serviceConfig.Restart = "always"; 152 serviceConfig.User = "minetest"; 153 serviceConfig.Group = "minetest"; 154 155 script = '' 156 cd /var/lib/minetest 157 158 exec ${pkgs.minetest}/bin/minetest ${lib.escapeShellArgs flags} 159 ''; 160 }; 161 }; 162}