lol

nixos/mchprs: init module

Co-authored-by: Ryan Lahfa <masterancpp@gmail.com>

+343 -1
+1 -1
nixos/doc/manual/release-notes/rl-2311.section.md
··· 6 6 7 7 ## New Services {#sec-release-23.11-new-services} 8 8 9 - - Create the first release note entry in this section! 9 + - [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server built for redstone. Available as [services.mchprs](#opt-services.mchprs.enable). 10 10 11 11 - [acme-dns](https://github.com/joohoi/acme-dns), a limited DNS server to handle ACME DNS challenges easily and securely. Available as [services.acme-dns](#opt-services.acme-dns.enable). 12 12
+1
nixos/modules/module-list.nix
··· 476 476 ./services/games/deliantra-server.nix 477 477 ./services/games/factorio.nix 478 478 ./services/games/freeciv.nix 479 + ./services/games/mchprs.nix 479 480 ./services/games/minecraft-server.nix 480 481 ./services/games/minetest-server.nix 481 482 ./services/games/openarena.nix
+341
nixos/modules/services/games/mchprs.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + let 6 + cfg = config.services.mchprs; 7 + settingsFormat = pkgs.formats.toml { }; 8 + 9 + whitelistFile = pkgs.writeText "whitelist.json" 10 + (builtins.toJSON 11 + (mapAttrsToList (n: v: { name = n; uuid = v; }) cfg.whitelist.list)); 12 + 13 + configToml = 14 + (removeAttrs cfg.settings [ "address" "port" ]) // 15 + { 16 + bind_address = cfg.settings.address + ":" + toString cfg.settings.port; 17 + whitelist = cfg.whitelist.enable; 18 + }; 19 + 20 + configTomlFile = settingsFormat.generate "Config.toml" configToml; 21 + in 22 + { 23 + options = { 24 + services.mchprs = { 25 + enable = mkEnableOption "MCHPRS"; 26 + 27 + declarativeSettings = mkOption { 28 + type = types.bool; 29 + default = false; 30 + description = mdDoc '' 31 + Whether to use a declarative configuration for MCHPRS. 32 + ''; 33 + }; 34 + 35 + declarativeWhitelist = mkOption { 36 + type = types.bool; 37 + default = false; 38 + description = mdDoc '' 39 + Whether to use a declarative whitelist. 40 + The options {option}`services.mchprs.whitelist.list` 41 + will be applied if and only if set to `true`. 42 + ''; 43 + }; 44 + 45 + dataDir = mkOption { 46 + type = types.path; 47 + default = "/var/lib/mchprs"; 48 + description = mdDoc '' 49 + Directory to store MCHPRS database and other state/data files. 50 + ''; 51 + }; 52 + 53 + openFirewall = mkOption { 54 + type = types.bool; 55 + default = false; 56 + description = mdDoc '' 57 + Whether to open ports in the firewall for the server. 58 + Only has effect when 59 + {option}`services.mchprs.declarativeSettings` is `true`. 60 + ''; 61 + }; 62 + 63 + maxRuntime = mkOption { 64 + type = types.str; 65 + default = "infinity"; 66 + example = "7d"; 67 + description = mdDoc '' 68 + Automatically restart the server after 69 + {option}`services.mchprs.maxRuntime`. 70 + The time span format is described here: 71 + https://www.freedesktop.org/software/systemd/man/systemd.time.html#Parsing%20Time%20Spans. 72 + If `null`, then the server is not restarted automatically. 73 + ''; 74 + }; 75 + 76 + package = mkOption { 77 + type = types.package; 78 + default = pkgs.mchprs; 79 + defaultText = literalExpression "pkgs.mchprs"; 80 + description = mdDoc "Version of MCHPRS to run."; 81 + }; 82 + 83 + settings = mkOption { 84 + type = types.submodule { 85 + freeformType = settingsFormat.type; 86 + 87 + options = { 88 + port = mkOption { 89 + type = types.port; 90 + default = 25565; 91 + description = mdDoc '' 92 + Port for the server. 93 + Only has effect when 94 + {option}`services.mchprs.declarativeSettings` is `true`. 95 + ''; 96 + }; 97 + 98 + address = mkOption { 99 + type = types.str; 100 + default = "0.0.0.0"; 101 + description = mdDoc '' 102 + Address for the server. 103 + Please use enclosing square brackets when using ipv6. 104 + Only has effect when 105 + {option}`services.mchprs.declarativeSettings` is `true`. 106 + ''; 107 + }; 108 + 109 + motd = mkOption { 110 + type = types.str; 111 + default = "Minecraft High Performance Redstone Server"; 112 + description = mdDoc '' 113 + Message of the day. 114 + Only has effect when 115 + {option}`services.mchprs.declarativeSettings` is `true`. 116 + ''; 117 + }; 118 + 119 + chat_format = mkOption { 120 + type = types.str; 121 + default = "<{username}> {message}"; 122 + description = mdDoc '' 123 + How to format chat message interpolating `username` 124 + and `message` with curly braces. 125 + Only has effect when 126 + {option}`services.mchprs.declarativeSettings` is `true`. 127 + ''; 128 + }; 129 + 130 + max_players = mkOption { 131 + type = types.ints.positive; 132 + default = 99999; 133 + description = mdDoc '' 134 + Maximum number of simultaneous players. 135 + Only has effect when 136 + {option}`services.mchprs.declarativeSettings` is `true`. 137 + ''; 138 + }; 139 + 140 + view_distance = mkOption { 141 + type = types.ints.positive; 142 + default = 8; 143 + description = mdDoc '' 144 + Maximal distance (in chunks) between players and loaded chunks. 145 + Only has effect when 146 + {option}`services.mchprs.declarativeSettings` is `true`. 147 + ''; 148 + }; 149 + 150 + bungeecord = mkOption { 151 + type = types.bool; 152 + default = false; 153 + description = mdDoc '' 154 + Enable compatibility with 155 + [BungeeCord](https://github.com/SpigotMC/BungeeCord). 156 + Only has effect when 157 + {option}`services.mchprs.declarativeSettings` is `true`. 158 + ''; 159 + }; 160 + 161 + schemati = mkOption { 162 + type = types.bool; 163 + default = false; 164 + description = mdDoc '' 165 + Mimic the verification and directory layout used by the 166 + Open Redstone Engineers 167 + [Schemati plugin](https://github.com/OpenRedstoneEngineers/Schemati). 168 + Only has effect when 169 + {option}`services.mchprs.declarativeSettings` is `true`. 170 + ''; 171 + }; 172 + 173 + block_in_hitbox = mkOption { 174 + type = types.bool; 175 + default = true; 176 + description = mdDoc '' 177 + Allow placing blocks inside of players 178 + (hitbox logic is simplified). 179 + Only has effect when 180 + {option}`services.mchprs.declarativeSettings` is `true`. 181 + ''; 182 + }; 183 + 184 + auto_redpiler = mkOption { 185 + type = types.bool; 186 + default = true; 187 + description = mdDoc '' 188 + Use redpiler automatically. 189 + Only has effect when 190 + {option}`services.mchprs.declarativeSettings` is `true`. 191 + ''; 192 + }; 193 + }; 194 + }; 195 + default = { }; 196 + 197 + description = mdDoc '' 198 + Configuration for MCHPRS via `Config.toml`. 199 + See https://github.com/MCHPR/MCHPRS/blob/master/README.md for documentation. 200 + ''; 201 + }; 202 + 203 + whitelist = { 204 + enable = mkOption { 205 + type = types.bool; 206 + default = false; 207 + description = mdDoc '' 208 + Whether or not the whitelist (in `whitelist.json`) shoud be enabled. 209 + Only has effect when {option}`services.mchprs.declarativeSettings` is `true`. 210 + ''; 211 + }; 212 + 213 + list = mkOption { 214 + type = 215 + let 216 + minecraftUUID = types.strMatching 217 + "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" // { 218 + description = "Minecraft UUID"; 219 + }; 220 + in 221 + types.attrsOf minecraftUUID; 222 + default = { }; 223 + example = literalExpression '' 224 + { 225 + username1 = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; 226 + username2 = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"; 227 + }; 228 + ''; 229 + description = mdDoc '' 230 + Whitelisted players, only has an effect when 231 + {option}`services.mchprs.declarativeWhitelist` is 232 + `true` and the whitelist is enabled 233 + via {option}`services.mchprs.whitelist.enable`. 234 + This is a mapping from Minecraft usernames to UUIDs. 235 + You can use <https://mcuuid.net/> to get a 236 + Minecraft UUID for a username. 237 + ''; 238 + }; 239 + }; 240 + }; 241 + }; 242 + 243 + config = mkIf cfg.enable { 244 + users.users.mchprs = { 245 + description = "MCHPRS service user"; 246 + home = cfg.dataDir; 247 + createHome = true; 248 + isSystemUser = true; 249 + group = "mchprs"; 250 + }; 251 + users.groups.mchprs = { }; 252 + 253 + systemd.services.mchprs = { 254 + description = "MCHPRS Service"; 255 + wantedBy = [ "multi-user.target" ]; 256 + after = [ "network.target" ]; 257 + 258 + serviceConfig = { 259 + ExecStart = "${lib.getExe cfg.package}"; 260 + Restart = "always"; 261 + RuntimeMaxSec = cfg.maxRuntime; 262 + User = "mchprs"; 263 + WorkingDirectory = cfg.dataDir; 264 + 265 + StandardOutput = "journal"; 266 + StandardError = "journal"; 267 + 268 + # Hardening 269 + CapabilityBoundingSet = [ "" ]; 270 + DeviceAllow = [ "" ]; 271 + LockPersonality = true; 272 + MemoryDenyWriteExecute = true; 273 + PrivateDevices = true; 274 + PrivateTmp = true; 275 + PrivateUsers = true; 276 + ProtectClock = true; 277 + ProtectControlGroups = true; 278 + ProtectHome = true; 279 + ProtectHostname = true; 280 + ProtectKernelLogs = true; 281 + ProtectKernelModules = true; 282 + ProtectKernelTunables = true; 283 + ProtectProc = "invisible"; 284 + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; 285 + RestrictNamespaces = true; 286 + RestrictRealtime = true; 287 + RestrictSUIDSGID = true; 288 + SystemCallArchitectures = "native"; 289 + UMask = "0077"; 290 + }; 291 + 292 + preStart = 293 + (if cfg.declarativeSettings then '' 294 + if [ -e .declarativeSettings ]; then 295 + 296 + # Settings were declarative before, no need to back up anything 297 + cp -f ${configTomlFile} Config.toml 298 + 299 + else 300 + 301 + # Declarative settings for the first time, backup stateful files 302 + cp -b --suffix=.stateful ${configTomlFile} Config.toml 303 + 304 + echo "Autogenerated file that implies that this server configuration is managed declaratively by NixOS" \ 305 + > .declarativeSettings 306 + 307 + fi 308 + '' else '' 309 + if [ -e .declarativeSettings ]; then 310 + rm .declarativeSettings 311 + fi 312 + '') + (if cfg.declarativeWhitelist then '' 313 + if [ -e .declarativeWhitelist ]; then 314 + 315 + # Whitelist was declarative before, no need to back up anything 316 + ln -sf ${whitelistFile} whitelist.json 317 + 318 + else 319 + 320 + # Declarative whitelist for the first time, backup stateful files 321 + ln -sb --suffix=.stateful ${whitelistFile} whitelist.json 322 + 323 + echo "Autogenerated file that implies that this server's whitelist is managed declaratively by NixOS" \ 324 + > .declarativeWhitelist 325 + 326 + fi 327 + '' else '' 328 + if [ -e .declarativeWhitelist ]; then 329 + rm .declarativeWhitelist 330 + fi 331 + ''); 332 + }; 333 + 334 + networking.firewall = mkIf (cfg.declarativeSettings && cfg.openFirewall) { 335 + allowedUDPPorts = [ cfg.settings.port ]; 336 + allowedTCPPorts = [ cfg.settings.port ]; 337 + }; 338 + }; 339 + 340 + meta.maintainers = with maintainers; [ gdd ]; 341 + }