From 9080b2eadff00772cc4d9aac3c0ec362f9d8748e Mon Sep 17 00:00:00 2001 From: Chris Ostrouchov Date: Mon, 20 Aug 2018 19:34:03 -0400 Subject: [PATCH 1/2] minecraft-server: 1.12.2 -> 1.13.2 Update minecraft client to 1.13.2. The url is not as nice as before but it is the one provided by mojang. Adds 1_13_2, 1_13_1 as well. https://minecraft.net/en-us/download/server --- pkgs/games/minecraft-server/default.nix | 82 ++++++++++++++++--------- pkgs/top-level/all-packages.nix | 8 ++- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/pkgs/games/minecraft-server/default.nix b/pkgs/games/minecraft-server/default.nix index 050e0126fa7..c2f20f53e9a 100644 --- a/pkgs/games/minecraft-server/default.nix +++ b/pkgs/games/minecraft-server/default.nix @@ -1,37 +1,63 @@ { stdenv, fetchurl, jre }: -stdenv.mkDerivation rec { - name = "minecraft-server-${version}"; - version = "1.13.2"; +let + common = { version, sha256, url }: + stdenv.mkDerivation (rec { + name = "minecraft-server-${version}"; + inherit version; - src = fetchurl { - # Old url - # https://s3.amazonaws.com/Minecraft.Download/versions/${version}/minecraft_server.${version}.jar + src = fetchurl { + inherit url sha256; + }; + + preferLocalBuild = true; + + installPhase = '' + mkdir -p $out/bin $out/lib/minecraft + cp -v $src $out/lib/minecraft/server.jar + + cat > $out/bin/minecraft-server << EOF + #!/bin/sh + exec ${jre}/bin/java \$@ -jar $out/lib/minecraft/server.jar nogui + EOF + + chmod +x $out/bin/minecraft-server + ''; + + phases = "installPhase"; + + meta = { + description = "Minecraft Server"; + homepage = "https://minecraft.net"; + license = stdenv.lib.licenses.unfreeRedistributable; + platforms = stdenv.lib.platforms.unix; + maintainers = with stdenv.lib.maintainers; [ thoughtpolice tomberek costrouc]; + }; + }); + +in { + minecraft-server_1_13_2 = common { + version = "1.13.2"; url = "https://launcher.mojang.com/v1/objects/3737db93722a9e39eeada7c27e7aca28b144ffa7/server.jar"; sha256 = "13h8dxrrgqa1g6sd7aaw26779hcsqsyjm7xm0sknifn54lnamlzz"; }; - preferLocalBuild = true; - - installPhase = '' - mkdir -p $out/bin $out/lib/minecraft - cp -v $src $out/lib/minecraft/server.jar - - cat > $out/bin/minecraft-server << EOF - #!/bin/sh - exec ${jre}/bin/java \$@ -jar $out/lib/minecraft/server.jar nogui - EOF - - chmod +x $out/bin/minecraft-server - ''; - - phases = "installPhase"; - - meta = { - description = "Minecraft Server"; - homepage = "https://minecraft.net"; - license = stdenv.lib.licenses.unfreeRedistributable; - platforms = stdenv.lib.platforms.unix; - maintainers = [ stdenv.lib.maintainers.thoughtpolice stdenv.lib.maintainers.tomberek ]; + minecraft-server_1_13_1 = common { + version = "1.13.1"; + url = "https://launcher.mojang.com/mc/game/1.13.1/server/fe123682e9cb30031eae351764f653500b7396c9/server.jar"; + sha256 = "1lak29b7dm0w1cmzjn9gyix6qkszwg8xgb20hci2ki2ifrz099if"; }; + + minecraft-server_1_13_0 = common { + version = "1.13.0"; + url = "https://launcher.mojang.com/mc/game/1.13/server/d0caafb8438ebd206f99930cfaecfa6c9a13dca0/server.jar"; + sha256 = "1fahqnylxzbvc0fdsqk0x15z40mcc5b7shrckab1qcsdj0kkjvz7"; + }; + + minecraft-server_1_12_2 = common { + version = "1.12.2"; + url = "https://s3.amazonaws.com/Minecraft.Download/versions/1.12.2/minecraft_server.1.12.2.jar"; + sha256 = "0zhnac6yvkdgdaag0gb0fgrkgizbwrpf7s76yqdiknfswrs947zy"; + }; + } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 9eb901ff307..78ba9f9d442 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -20770,7 +20770,13 @@ in minecraft = callPackage ../games/minecraft { }; - minecraft-server = callPackage ../games/minecraft-server { }; + minecraft-server = minecraft-server_1_13_2; + + inherit (callPackages ../games/minecraft-server { }) + minecraft-server_1_13_2 + minecraft-server_1_13_1 + minecraft-server_1_13_0 + minecraft-server_1_12_2; moon-buggy = callPackage ../games/moon-buggy {}; From 58c89ec26a5d3c34e34bcb9f23db9fc62d7cf98a Mon Sep 17 00:00:00 2001 From: Chris Ostrouchov Date: Mon, 20 Aug 2018 19:35:22 -0400 Subject: [PATCH 2/2] nixos/mincraft-server: refactor - allow for options to (added 2 options): - agree to eula (eula.txt) true/false will create symlink over existing eula.txt to `/nix/store/...`. - whitelist users (optional and will symlink over existing whitelist.json and create backup) - server.properties can be configured with the serverProperties option. If there is an existing server.properties it will copy it to a server.properties.old to keep the old one. server.properties MUST be writable thus symlinking is not an option. - all ports that are stated in `server.properties` are exposed properly in the firewall. (infinisil) nixos/minecraft-server: Fix, refactor and polish Adds an option `declarative` (defaulted to false), in order to stay (mostly) backwards compatible. The only thing that's not backwards compatible is that you now need to agree to the EULA on evaluation time, but that's guarded by an assertion and therefore doesn't need a release note. --- .../services/games/minecraft-server.nix | 201 ++++++++++++++++-- 1 file changed, 181 insertions(+), 20 deletions(-) diff --git a/nixos/modules/services/games/minecraft-server.nix b/nixos/modules/services/games/minecraft-server.nix index f50d2897843..7d26d150165 100644 --- a/nixos/modules/services/games/minecraft-server.nix +++ b/nixos/modules/services/games/minecraft-server.nix @@ -4,8 +4,41 @@ with lib; let cfg = config.services.minecraft-server; -in -{ + + # We don't allow eula=false anyways + eulaFile = builtins.toFile "eula.txt" '' + # eula.txt managed by NixOS Configuration + eula=true + ''; + + whitelistFile = pkgs.writeText "whitelist.json" + (builtins.toJSON + (mapAttrsToList (n: v: { name = n; uuid = v; }) cfg.whitelist)); + + cfgToString = v: if builtins.isBool v then boolToString v else toString v; + + serverPropertiesFile = pkgs.writeText "server.properties" ('' + # server.properties managed by NixOS configuration + '' + concatStringsSep "\n" (mapAttrsToList + (n: v: "${n}=${cfgToString v}") cfg.serverProperties)); + + + # To be able to open the firewall, we need to read out port values in the + # server properties, but fall back to the defaults when those don't exist. + # These defaults are from https://minecraft.gamepedia.com/Server.properties#Java_Edition_3 + defaultServerPort = 25565; + + serverPort = cfg.serverProperties.server-port or defaultServerPort; + + rconPort = if cfg.serverProperties.enable-rcon or false + then cfg.serverProperties."rcon.port" or 25575 + else null; + + queryPort = if cfg.serverProperties.enable-query or false + then cfg.serverProperties."query.port" or 25565 + else null; + +in { options = { services.minecraft-server = { @@ -13,10 +46,32 @@ in type = types.bool; default = false; description = '' - If enabled, start a Minecraft Server. The listening port for - the server is always 25565. The server + If enabled, start a Minecraft Server. The server data will be loaded from and saved to - ${cfg.dataDir}. + . + ''; + }; + + declarative = mkOption { + type = types.bool; + default = false; + description = '' + Whether to use a declarative Minecraft server configuration. + Only if set to true, the options + and + will be + applied. + ''; + }; + + eula = mkOption { + type = types.bool; + default = false; + description = '' + Whether you agree to + + Mojangs EULA. This option must be set to + true to run Minecraft server. ''; }; @@ -24,7 +79,7 @@ in type = types.path; default = "/var/lib/minecraft"; description = '' - Directory to store minecraft database and other state/data files. + Directory to store Minecraft database and other state/data files. ''; }; @@ -32,21 +87,84 @@ in type = types.bool; default = false; description = '' - Whether to open ports in the firewall (if enabled) for the server. + Whether to open ports in the firewall for the server. ''; }; + whitelist = mkOption { + type = let + minecraftUUID = types.strMatching + "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" // { + description = "Minecraft UUID"; + }; + in types.attrsOf minecraftUUID; + default = {}; + description = '' + Whitelisted players, only has an effect when + is + true and the whitelist is enabled + via by + setting white-list to true. + This is a mapping from Minecraft usernames to UUIDs. + You can use to get a + Minecraft UUID for a username. + ''; + example = literalExample '' + { + username1 = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + username2 = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"; + }; + ''; + }; + + serverProperties = mkOption { + type = with types; attrsOf (either bool (either int str)); + default = {}; + example = literalExample '' + { + server-port = 43000; + difficulty = 3; + gamemode = 1; + max-players = 5; + motd = "NixOS Minecraft server!"; + white-list = true; + enable-rcon = true; + "rcon.password" = "hunter2"; + } + ''; + description = '' + Minecraft server properties for the server.properties file. Only has + an effect when + is set to true. See + + for documentation on these values. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.minecraft-server; + defaultText = "pkgs.minecraft-server"; + example = literalExample "pkgs.minecraft-server_1_12_2"; + description = "Version of minecraft-server to run."; + }; + jvmOpts = mkOption { - type = types.str; + type = types.separatedString " "; default = "-Xmx2048M -Xms2048M"; - description = "JVM options for the Minecraft Service."; + # Example options from https://minecraft.gamepedia.com/Tutorials/Server_startup_script + example = "-Xmx2048M -Xms4092M -XX:+UseG1GC -XX:+CMSIncrementalPacing " + + "-XX:+CMSClassUnloadingEnabled -XX:ParallelGCThreads=2 " + + "-XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10"; + description = "JVM options for the Minecraft server."; }; }; }; config = mkIf cfg.enable { + users.users.minecraft = { - description = "Minecraft Server Service user"; + description = "Minecraft server service user"; home = cfg.dataDir; createHome = true; uid = config.ids.uids.minecraft; @@ -57,17 +175,60 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; - serviceConfig.Restart = "always"; - serviceConfig.User = "minecraft"; - script = '' - cd ${cfg.dataDir} - exec ${pkgs.minecraft-server}/bin/minecraft-server ${cfg.jvmOpts} - ''; + serviceConfig = { + ExecStart = "${cfg.package}/bin/minecraft-server ${cfg.jvmOpts}"; + Restart = "always"; + User = "minecraft"; + WorkingDirectory = cfg.dataDir; + }; + + preStart = '' + ln -sf ${eulaFile} eula.txt + '' + (if cfg.declarative then '' + + if [ -e .declarative ]; then + + # Was declarative before, no need to back up anything + ln -sf ${whitelistFile} whitelist.json + cp -f ${serverPropertiesFile} server.properties + + else + + # Declarative for the first time, backup stateful files + ln -sb --suffix=.stateful ${whitelistFile} whitelist.json + cp -b --suffix=.stateful ${serverPropertiesFile} server.properties + + # server.properties must have write permissions, because every time + # the server starts it first parses the file and then regenerates it.. + chmod +w server.properties + echo "Autogenerated file that signifies that this server configuration is managed declaratively by NixOS" \ + > .declarative + + fi + '' else '' + if [ -e .declarative ]; then + rm .declarative + fi + ''); }; - networking.firewall = mkIf cfg.openFirewall { - allowedUDPPorts = [ 25565 ]; - allowedTCPPorts = [ 25565 ]; - }; + networking.firewall = mkIf cfg.openFirewall (if cfg.declarative then { + allowedUDPPorts = [ serverPort ]; + allowedTCPPorts = [ serverPort ] + ++ optional (! isNull queryPort) queryPort + ++ optional (! isNull rconPort) rconPort; + } else { + allowedUDPPorts = [ defaultServerPort ]; + allowedTCPPorts = [ defaultServerPort ]; + }); + + assertions = [ + { assertion = cfg.eula; + message = "You must agree to Mojangs EULA to run minecraft-server." + + " Read https://account.mojang.com/documents/minecraft_eula and" + + " set `services.minecraft-server.eula` to `true` if you agree."; + } + ]; + }; }