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