diff --git a/hosts/greddost/configuration.nix b/hosts/greddost/configuration.nix index b17206e..ccf5034 100644 --- a/hosts/greddost/configuration.nix +++ b/hosts/greddost/configuration.nix @@ -10,18 +10,10 @@ ../../hardware-configuration.nix ../../base.nix + + ../../services/minecraft ]; - - services.minecraft-server = { - enable = true; - eula = true; - package = pkgs.unstable.minecraft-server; - dataDir = "/run/minecraft"; #"/fast/minecraft"; - jvmOpts = "-Xmx8192M -Xms8192M -XX:+UseG1GC -XX:ParallelGCThreads=2 -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10"; - }; - - nixpkgs.config.packageOverrides = pkgs: { unstable = (import ) { }; }; @@ -37,7 +29,26 @@ networking.hostName = "greddost"; # Define your hostname. - networking.interfaces.ens18.useDHCP = true; + networking.interfaces.ens18.useDHCP = false; + + networking.defaultGateway = "129.241.210.129"; + networking.interfaces.ens18.ipv4 = { + addresses = [ + { + address = "129.241.210.174"; + prefixLength = 25; + } + ]; + }; + networking.interfaces.ens18.ipv6 = { + addresses = [ + { + address = "2001:700:300:1900::174"; + prefixLength = 64; + } + ]; + }; + networking.nameservers = [ "129.241.0.200" "129.241.0.201" ]; # Open ports in the firewall. networking.firewall.allowedTCPPorts = [ 25565 ]; diff --git a/pkgs/minecraft-server-fabric/default.nix b/pkgs/minecraft-server-fabric/default.nix new file mode 100644 index 0000000..a011a76 --- /dev/null +++ b/pkgs/minecraft-server-fabric/default.nix @@ -0,0 +1,43 @@ +{ callPackage, writeTextFile, writeShellScriptBin, minecraft-server, jre_headless }: + +let + loader = callPackage ./generate-loader.nix {}; + log4j = writeTextFile { + name = "log4j.xml"; + text = '' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''; + }; +in +writeShellScriptBin "minecraft-server" '' + echo "serverJar=${minecraft-server}/lib/minecraft/server.jar" >> fabric-server-launcher.properties + exec ${jre_headless}/bin/java -Dlog4j.configurationFile=${log4j} $@ -jar ${loader} nogui +'' diff --git a/pkgs/minecraft-server-fabric/generate-loader.nix b/pkgs/minecraft-server-fabric/generate-loader.nix new file mode 100644 index 0000000..e2e4857 --- /dev/null +++ b/pkgs/minecraft-server-fabric/generate-loader.nix @@ -0,0 +1,38 @@ +{ lib, fetchurl, stdenv, unzip, zip, jre_headless }: + +let + lock = import ./lock.nix; + libraries = lib.forEach lock.libraries fetchurl; +in +stdenv.mkDerivation { + name = "fabric-server-launch.jar"; + nativeBuildInputs = [ unzip zip jre_headless ]; + + libraries = libraries; + + buildPhase = '' + for i in $libraries; do + unzip -o $i + done + + cat > META-INF/MANIFEST.MF << EOF + Manifest-Version: 1.0 + Main-Class: net.fabricmc.loader.impl.launch.server.FabricServerLauncher + Name: org/objectweb/asm/ + Implementation-Version: 9.2 + EOF + + cat > fabric-server-launch.properties << EOF + launch.mainClass=net.fabricmc.loader.impl.launch.knot.KnotServer + EOF + ''; + + installPhase = '' + jar cmvf META-INF/MANIFEST.MF "server.jar" . + zip -d server.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*.DSA' + cp server.jar "$out" + ''; + + phases = [ "buildPhase" "installPhase" ]; +} + diff --git a/pkgs/minecraft-server-fabric/generate-lock-nix.sh b/pkgs/minecraft-server-fabric/generate-lock-nix.sh new file mode 100755 index 0000000..fba715a --- /dev/null +++ b/pkgs/minecraft-server-fabric/generate-lock-nix.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p bash curl jq +curl https://meta.fabricmc.net/v2/versions/loader/1.18.1/0.12.12/server/json \ +| jq -r ' + .mainClass, + (.libraries[] + | .url as $url + | .name | split(":") as [$dir, $name, $version] + |"\($name)-\($version).zip|\($url)\($dir|sub("\\.";"/";"g"))/\($name)/\($version)/\($name)-\($version).jar" + )' \ +| { + echo '{' + read mainClass; + echo " mainClass = \"$mainClass\";" + echo " libraries = [" + while IFS="|" read name url; do + hash=$(nix-prefetch-url $url); + echo " { name = \"$name\"; sha256 = \"$hash\"; url = \"$url\"; }" + done + echo " ];" + echo '}' +} diff --git a/pkgs/minecraft-server-fabric/lock.nix b/pkgs/minecraft-server-fabric/lock.nix new file mode 100644 index 0000000..c625c45 --- /dev/null +++ b/pkgs/minecraft-server-fabric/lock.nix @@ -0,0 +1,16 @@ +{ + mainClass = "net.fabricmc.loader.impl.launch.knot.KnotServer"; + libraries = [ + { name = "tiny-mappings-parser-0.3.0+build.17.zip"; sha256 = "19kvhxfk5v01f2rvl7j02vqhn3nd2bh5jsgbk44rpzqv9f6074db"; url = "https://maven.fabricmc.net/net/fabricmc/tiny-mappings-parser/0.3.0+build.17/tiny-mappings-parser-0.3.0+build.17.jar"; } + { name = "sponge-mixin-0.10.7+mixin.0.8.4.zip"; sha256 = "18m5wksd9vjp676cxapkggnz8s3f8j89phln8gy5n8vxlrli8n0d"; url = "https://maven.fabricmc.net/net/fabricmc/sponge-mixin/0.10.7+mixin.0.8.4/sponge-mixin-0.10.7+mixin.0.8.4.jar"; } + { name = "tiny-remapper-0.6.0.zip"; sha256 = "1ynjfxg7cj9rd9c4l450w7yp20p2csjdpnk3mcx5bdkjzhbgvgzf"; url = "https://maven.fabricmc.net/net/fabricmc/tiny-remapper/0.6.0/tiny-remapper-0.6.0.jar"; } + { name = "access-widener-2.0.1.zip"; sha256 = "0a7s4x6dbaa9p59ps7pidzwrs0xwy5i17s35xrgh58i26szlsaxm"; url = "https://maven.fabricmc.net/net/fabricmc/access-widener/2.0.1/access-widener-2.0.1.jar"; } + { name = "asm-9.2.zip"; sha256 = "1xa7kccwmcqcdw1xly6n2frzhk56m8ma9v7h764g73ckf56zxm5r"; url = "https://maven.fabricmc.net/org/ow2/asm/asm/9.2/asm-9.2.jar"; } + { name = "asm-analysis-9.2.zip"; sha256 = "1i1kyirizs5sm2v0f06sdz86mbmyn61vjr9d9p8p5h1i2x9bx3w7"; url = "https://maven.fabricmc.net/org/ow2/asm/asm-analysis/9.2/asm-analysis-9.2.jar"; } + { name = "asm-commons-9.2.zip"; sha256 = "19p04mr14ahndba65v4krbvf4p5syf8wz0fp5i9bnf5270qyak5y"; url = "https://maven.fabricmc.net/org/ow2/asm/asm-commons/9.2/asm-commons-9.2.jar"; } + { name = "asm-tree-9.2.zip"; sha256 = "04g0zb7v65iz4k2m2grdpbv8jjryrzkkw7ww23yfp94i6399pgxa"; url = "https://maven.fabricmc.net/org/ow2/asm/asm-tree/9.2/asm-tree-9.2.jar"; } + { name = "asm-util-9.2.zip"; sha256 = "16759v4hh3ijpf4cglrxybz29x2hiylhsa388y09m2mf679kqnzz"; url = "https://maven.fabricmc.net/org/ow2/asm/asm-util/9.2/asm-util-9.2.jar"; } + { name = "intermediary-1.18.1.zip"; sha256 = "1rfz2gazvnivn6hlqiyjpiaycz8va87n5czy1p6w3lnrlfggj2i9"; url = "https://maven.fabricmc.net/net/fabricmc/intermediary/1.18.1/intermediary-1.18.1.jar"; } + { name = "fabric-loader-0.12.12.zip"; sha256 = "070dpcp7kcj4xr75wp1j6pb1bgfzllwg8xmqk3sk79jfqiqwzizw"; url = "https://maven.fabricmc.net/net/fabricmc/fabric-loader/0.12.12/fabric-loader-0.12.12.jar"; } + ]; +} diff --git a/pkgs/minecraft-server/1_18_1.nix b/pkgs/minecraft-server/1_18_1.nix new file mode 100644 index 0000000..58b5c69 --- /dev/null +++ b/pkgs/minecraft-server/1_18_1.nix @@ -0,0 +1,38 @@ +{ lib, stdenv, fetchurl, nixosTests, jre_headless }: +stdenv.mkDerivation { + pname = "minecraft-server"; + version = "1.18.1"; + + src = fetchurl { + url = "https://launcher.mojang.com/v1/objects/125e5adf40c659fd3bce3e66e67a16bb49ecc1b9/server.jar"; + # sha1 because that comes from mojang via api + sha1 = "125e5adf40c659fd3bce3e66e67a16bb49ecc1b9"; + }; + + 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_headless}/bin/java \$@ -jar $out/lib/minecraft/server.jar nogui + EOF + chmod +x $out/bin/minecraft-server + ''; + + dontUnpack = true; + + passthru = { + tests = { inherit (nixosTests) minecraft-server; }; + updateScript = ./update.sh; + }; + + meta = with lib; { + description = "Minecraft Server"; + homepage = "https://minecraft.net"; + license = licenses.unfreeRedistributable; + platforms = platforms.unix; + maintainers = with maintainers; [ thoughtpolice tomberek costrouc ]; + }; +} diff --git a/services/minecraft/default.nix b/services/minecraft/default.nix new file mode 100644 index 0000000..a0b6914 --- /dev/null +++ b/services/minecraft/default.nix @@ -0,0 +1,158 @@ +{config, lib, pkgs, ... }: + +{ + + imports = [ ./minecraft-server-fabric.nix ]; + + environment.systemPackages = with pkgs; [ + mcron + ]; + + pvv.minecraft-server-fabric = { + enable = true; + eula = true; + + package = pkgs.callPackage ../../pkgs/minecraft-server-fabric { minecraft-server = (pkgs.callPackage ../../pkgs/minecraft-server/1_18_1.nix { }); }; + jvmOpts = "-Xms10G -Xmx10G -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:+ParallelRefProcEnabled"; + + serverProperties = { + view-distance = 12; + simulation-distance = 12; + + enable-command-block = true; + + gamemode = "survival"; + difficulty = "normal"; + + white-list = true; + + enable-rcon = true; + "rcon.password" = "pvv"; + }; + + dataDir = "/fast/minecraft-pvv"; + + mods = [ + (pkgs.fetchurl { # Fabric API is a common dependency for fabric based mods + url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/0.44.0+1.18/fabric-api-0.44.0+1.18.jar"; + sha256 = "0mlmj7mj073a48s8zgc1km0jwkphz01c1fvivn4mw37lbm2p4834"; + }) + (pkgs.fetchurl { # Lithium is a 100% vanilla compatible optimization mod + url = "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.18.1-0.7.6/lithium-fabric-mc1.18.1-0.7.6.jar"; + sha256 = "1fw1ikg578v4i6bmry7810a3q53h8yspxa3awdz7d746g91g8lf7"; + }) + (pkgs.fetchurl { # Starlight is the lighting engine of papermc + url = "https://cdn.modrinth.com/data/H8CaAYZC/versions/Starlight%201.0.0%201.18.x/starlight-1.0.0+fabric.d0a3220.jar"; + sha256 = "0bv9im45hhc8n6x57lakh2rms0g5qb7qfx8qpx8n6mbrjjz6gla1"; + }) + (pkgs.fetchurl { # Krypton is a linux optimized optimizer for minecrafts networking system + url = "https://cdn.modrinth.com/data/fQEb0iXm/versions/0.1.6/krypton-0.1.6.jar"; + sha256 = "1ribvbww4msrfdnzlxipk8kpzz7fnwnd4q6ln6mpjlhihcjb3hni"; + }) + (pkgs.fetchurl { # C2ME is a parallelizer for chunk loading and generation, experimental!!! + url = "https://cdn.modrinth.com/data/VSNURh3q/versions/0.2.0+alpha.5.104%201.18.1/c2me-fabric-mc1.18.1-0.2.0+alpha.5.104-all.jar"; + sha256 = "13zrpsg61fynqnnlm7dvy3ihxk8khlcqsif68ak14z7kgm4py6nw"; + }) + (pkgs.fetchurl { # Spark is a profiler for minecraft + url = "https://ci.lucko.me/job/spark/251/artifact/spark-fabric/build/libs/spark-fabric.jar"; + sha256 = "1clvi5v7a14ba23jbka9baz99h6wcfjbadc8kkj712fmy2h0sx07"; + }) + #(pkgs.fetchurl { # Carpetmod gives you tps views in the tab menu, + # # but also adds a lot of optional serverside vanilla+ features (which we arent using). + # # So probably want something else + # url = "https://github.com/gnembon/fabric-carpet/releases/download/1.4.56/fabric-carpet-1.18-1.4.56+v211130.jar"; + # sha256 = "0rvl2yb8xymla8c052j07gqkqfkz4h5pxf6aip2v9v0h8r84p9hf"; + #}) + ]; + + whitelist = { + gunalx = "913a21ae-3a11-4178-a192-401490ca0891"; + eirikwitt = "1689e626-1cc8-4b91-81c4-0632fd34eb19"; + Rockj = "202c0c91-a4e0-4b45-8c1b-fc51a8956c0a"; + paddishar = "326845aa-4b45-4cd9-8108-7816e10a9828"; + nordyorn = "f253cddf-a520-42ab-85d3-713992746e42"; + hell04 = "c681df2a-6a30-4c66-b70d-742eb68bbc04"; + steinarh = "bd8c419e-e6dc-4fc5-ac62-b92f98c1abc9"; + EastTown2000 = "f273ed2e-d3ba-43fc-aff4-3e800cdf25e1"; + DirDanner = "5b5476a2-1138-476b-9ff1-1f39f834a428"; + asgeirbj = "dbd5d89f-3d8a-4662-ad15-6c4802d0098f"; + Linke03 = "0dbc661d-898a-47ff-a371-32b7bd76b78b"; + somaen = "cc0bdd13-4304-4160-80e7-8f043446fa83"; + einaman = "39f45df3-423d-4274-9ef9-c9b7575e3804"; + liseu = "c8f4d9d8-3140-4c35-9f66-22bc351bb7e6"; + torsteno = "ae1e7b15-a0de-4244-9f73-25b68427e34a"; + simtind = "39c03c95-d628-4ccc-843d-ce1332462d9e"; + aellaie = "c585605d-24bb-4d75-ba9c-0064f6a39328"; + PerKjelsvik = "5df69f17-27c9-4426-bcae-88b435dfae73"; + CelestialCry = "9e34d192-364e-4566-883a-afc868c4224d"; + terjesc = "993d70e8-6f9b-4094-813c-050d1a90be62"; + maxelost = "bf465915-871a-4e3e-a80c-061117b86b23"; + "4ce1" = "8a9b4926-0de8-43f0-bcde-df1442dee1d0"; + exponential = "1ebcca9d-0964-48f3-9154-126a9a7e64f6"; + Dodsorbot = "3baa9d58-32e4-465e-80bc-9dcb34e23e1d"; + HFANTOM = "cd74d407-7fb0-4454-b3f4-c0b4341fde18"; + Ghostmaker = "96465eee-e665-49ab-9346-f12d5a040624"; + soonhalle = "61a8e674-7c7a-4120-80d1-4453a5993350"; + MasterMocca = "481e6dac-9a17-4212-9664-645c3abe232f"; + soulprayfree = "cfb1fb23-5115-4fe2-9af9-00a02aea9bf8"; + calibwam = "0d5d5209-bb7c-4006-9451-fb85d7d52618"; + Skuggen = "f0ccee0b-741a-413a-b8e6-d04552b9d78a"; + Sivertsen3 = "cefac1a6-52a7-4781-be80-e7520f758554"; + vafflonaut = "4d864d5c-74e2-4f29-b57d-50dea76aaabd"; + Dhila = "c71d6c23-14d7-4daf-ae59-cbf0caf45681"; + remorino = "2972ab22-96b3-462d-ab4d-9b6b1775b9bb"; + SamuelxJackson = "f140e4aa-0a19-48ab-b892-79b24bd82c1e"; + ToanBuiDuc = "a3c54742-4caf-4334-8bbb-6402a8eb4268"; + Joces123 = "ecbcfbf9-9bcc-49f0-9435-f2ac2b3217c1"; + brunsviken = "75ff5f0e-8adf-4807-a7f0-4cb66f81cb7f"; + oscarsb1 = "9460015a-65cc-4a2f-9f91-b940b6ce7996"; + CVi = "6f5691ce-9f9c-4310-84aa-759d2f9e138e"; + Tawos = "0b98e55c-10cf-4b23-85d3-d15407431ace"; + evenhunn = "8751581b-cc5f-4f8b-ae1e-34d90127e074"; + q41 = "a080e5b4-10ee-4d6f-957e-aa5053bb1046"; + jesper001 = "fbdf3ceb-eaa9-4aeb-94c2-a587cde41774"; + finninde = "f58afd00-28cd-48dd-a74a-6c1d76b57f66"; + GameGuru999 = "535f2188-a4a4-4e54-bec6-74977bee09ab"; + MinusOneKelvin = "b6b973bf-1e35-4a58-803b-a555fd90a172"; + SuperRagna = "e2c32136-e510-41b1-84c0-41baeccfb0b9"; + Zamazaki = "d4411eca-401a-4565-9451-5ced6f48f23f"; + supertheodor = "610c4e86-0ecc-4e7a-bffc-35a2e7d90aa6"; + Minelost = "22ae2a1f-cfd9-4f10-9e41-e7becd34aba8"; + Bjand = "aed136b6-17f7-4ce1-8a7b-a09eb1694ccf"; + Dandellion = "f393413b-59fc-49d7-a5c4-83a5d177132c"; + Shogori = "f9d571bd-5754-46e8-aef8-e89b38a6be9b"; + Caragath = "f8d34f3a-55c3-4adc-b8d8-73a277f979e8"; + Shmaapqueen = "425f2eef-1a9d-4626-9ba3-cd58156943dc"; + Liquidlif3 = "420482b3-885f-4951-ba1e-30c22438a7e0"; + newtonseple = "7d8bf9ca-0499-4cb7-9d6a-daabf80482b6"; + nainis = "2eaf3736-decc-4e11-9a44-af2df0ee7c81"; + Devolan = "87016228-76b2-434f-a963-33b005ae9e42"; + zSkyler = "c92169e4-ca14-4bd5-9ea2-410fe956abe2"; + Cryovat = "7127d743-873e-464b-927a-d23b9ad5b74a"; + cybrhuman = "14a67926-cff0-4542-a111-7f557d10cc67"; + stinl = "3a08be01-1e74-4d68-88d1-07d0eb23356f"; + Mirithing = "7b327f51-4f1b-4606-88c7-378eff1b92b1"; + "_dextra" = "4b7b4ee7-eb5b-48fd-88c3-1cc68f06acda"; + Soraryuu = "0d5ffe48-e64f-4d6d-9432-f374ea8ec10c"; + klarken1 = "d6967cb8-2bc6-4db7-a093-f0770cce47df"; + }; + }; + + networking.firewall.allowedTCPPorts = [ 25565 ]; + networking.firewall.allowedUDPPorts = [ 25565 ]; + + systemd.services."minecraft-backup" = { + serviceConfig.Type = "oneshot"; + script = '' + ${pkgs.mcrcon}/bin/mcrcon -p pvv "say Starting Backup" "save-off" "save-all" + ${pkgs.rsync}/bin/rsync -aiz --delete ${config.pvv.minecraft-server-fabric.dataDir}/world /fast/backup # Where to put backup + ${pkgs.mcrcon}/bin/mcrcon -p pvv "save-all" "say Completed Backup" "save-on" "save-all" + ''; + }; + + systemd.timers."minecraft-backup" = { + wantedBy = ["timers.target"]; + timerConfig.OnCalendar = [ "hourly" ]; + }; + +} diff --git a/services/minecraft/minecraft-server-fabric.nix b/services/minecraft/minecraft-server-fabric.nix new file mode 100644 index 0000000..25784ab --- /dev/null +++ b/services/minecraft/minecraft-server-fabric.nix @@ -0,0 +1,180 @@ +{ lib, pkgs, config, ... }: + +with lib; + +let + cfg = config.pvv.minecraft-server-fabric; + + # 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)); + + 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.pvv.minecraft-server-fabric = { + enable = mkEnableOption "minecraft-server-fabric"; + + package = mkOption { + type = types.package; + }; + + 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. + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/minecraft-fabric"; + description = '' + Directory to store Minecraft database and other state/data files. + ''; + }; + + + 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 = literalExpression '' + { + username1 = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + username2 = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"; + }; + ''; + }; + + serverProperties = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = {}; + example = literalExpression '' + { + 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. + ''; + }; + + jvmOpts = mkOption { + type = types.separatedString " "; + default = "-Xmx2048M -Xms2048M"; + # 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."; + }; + + mods = mkOption { + type = types.listOf types.package; + example = literalExpression '' + [ + (pkgs.fetchurl { + url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/0.44.0+1.18/fabric-api-0.44.0+1.18.jar"; + sha256 = "0mlmj7mj073a48s8zgc1km0jwkphz01c1fvivn4mw37lbm2p4834"; + }) + ]; + ''; + description = "List of mods to put in the mods folder"; + }; + }; + + config = mkIf cfg.enable { + users.users.minecraft = { + description = "Minecraft server service user"; + home = cfg.dataDir; + createHome = true; + isSystemUser = true; + group = "minecraft"; + }; + users.groups.minecraft = {}; + + systemd.services.minecraft-server-fabric = { + description = "Minecraft Server Service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + ExecStart = "${cfg.package}/bin/minecraft-server ${cfg.jvmOpts}"; + Restart = "always"; + User = "minecraft"; + WorkingDirectory = cfg.dataDir; + }; + + preStart = '' + ln -sf ${eulaFile} eula.txt + ln -sf ${whitelistFile} whitelist.json + cp -f ${serverPropertiesFile} server.properties + + ln -sfn ${pkgs.linkFarmFromDrvs "fabric-mods" cfg.mods} mods + ''; + }; + + 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."; + } + ]; + }; +}