diff --git a/hosts/Gutterman/default.nix b/hosts/Gutterman/default.nix index ac1fdc1..f790576 100644 --- a/hosts/Gutterman/default.nix +++ b/hosts/Gutterman/default.nix @@ -10,6 +10,7 @@ ../../modules/nixos/programs/git.nix ../../modules/nixos/services/tailscale + ../../modules/nixos/services/gameserver/minecraft-server.nix ../../modules/nixos/system/headless.nix ../../modules/nixos/system/minimal.nix @@ -29,30 +30,11 @@ CacheFromLocalhost=true ''; - networking.firewall = { - allowedTCPPorts = [ - 8000 - 8001 - ]; - allowedUDPPorts = [ - 8000 - 8001 - ]; - }; - - environment.systemPackages = - let - nixpkgs-unstable = import inputs.nixpkgs-unstable { - system = "${pkgs.system}"; - config.allowUnfree = true; - }; - in [ + environment.systemPackages = [ pkgs.btop - nixpkgs-unstable.graalvmPackages.graalvm-oracle_17 - inputs.nixpkgs-pin.legacyPackages.${pkgs.system}.graalvm-ce pkgs.steamcmd ]; nixpkgs.hostPlatform = "x86_64-linux"; system.stateVersion = "25.05"; -} \ No newline at end of file +} diff --git a/modules/nixos/services/gameserver/minecraft-server.nix b/modules/nixos/services/gameserver/minecraft-server.nix new file mode 100644 index 0000000..46767a7 --- /dev/null +++ b/modules/nixos/services/gameserver/minecraft-server.nix @@ -0,0 +1,178 @@ +{ inputs, config, pkgs, lib, ... }: + + +{ + networking.firewall = { + allowedTCPPorts = [ 10000 ]; + allowedUDPPorts = [ 10000 ]; + }; + + users = { + users.minecraft = { + group = "minecraft"; + isSystemUser = true; + + home = "/var/lib/minecraft"; + createHome = true; + }; + groups.minecraft = {}; + }; + + environment.systemPackages = + let + nixpkgs-unstable = import inputs.nixpkgs-unstable { + system = "${pkgs.system}"; + config.allowUnfree = true; + }; + in [ + # to control the interactive server console + pkgs.screen + + nixpkgs-unstable.graalvmPackages.graalvm-oracle_17 + inputs.nixpkgs-pin.legacyPackages.${pkgs.system}.graalvm-ce + ]; + + environment.etc = { + "minecraft/java21_args".text = '' + -Xmx8G + -Xms8G + --add-modules=jdk.incubator.vector + -XX:+UseG1GC + -XX:MaxGCPauseMillis=200 + -XX:+UnlockExperimentalVMOptions + -XX:+UnlockDiagnosticVMOptions + -XX:+DisableExplicitGC + -XX:+AlwaysPreTouch + -XX:G1NewSizePercent=28 + -XX:G1MaxNewSizePercent=50 + -XX:G1HeapRegionSize=16M + -XX:G1ReservePercent=15 + -XX:G1MixedGCCountTarget=3 + -XX:InitiatingHeapOccupancyPercent=20 + -XX:G1MixedGCLiveThresholdPercent=90 + -XX:SurvivorRatio=32 + -XX:G1HeapWastePercent=5 + -XX:MaxTenuringThreshold=1 + -XX:+PerfDisableSharedMem + -XX:G1SATBBufferEnqueueingThresholdPercent=30 + -XX:G1ConcMarkStepDurationMillis=5 + -XX:G1RSetUpdatingPauseTimePercent=0 + -XX:+UseNUMA + -XX:-DontCompileHugeMethods + -XX:MaxNodeLimit=240000 + -XX:NodeLimitFudgeFactor=8000 + -XX:ReservedCodeCacheSize=400M + -XX:NonNMethodCodeHeapSize=12M + -XX:ProfiledCodeHeapSize=194M + -XX:NonProfiledCodeHeapSize=194M + -XX:NmethodSweepActivity=1 + -XX:+UseFastUnorderedTimeStamps + -XX:+UseCriticalJavaThreadPriority + -XX:AllocatePrefetchStyle=3 + -XX:+AlwaysActAsServerClassMachine + -XX:+UseTransparentHugePages + -XX:LargePageSizeInBytes=2M + -XX:+UseLargePages + -XX:+EagerJVMCI + -XX:+UseStringDeduplication + -XX:+UseAES + -XX:+UseAESIntrinsics + -XX:+UseFMA + -XX:+UseLoopPredicate + -XX:+RangeCheckElimination + -XX:+OptimizeStringConcat + -XX:+UseCompressedOops + -XX:+UseThreadPriorities + -XX:+OmitStackTraceInFastThrow + -XX:+RewriteBytecodes + -XX:+RewriteFrequentPairs + -XX:+UseFPUForSpilling + -XX:+UseFastStosb + -XX:+UseNewLongLShift + -XX:+UseVectorCmov + -XX:+UseXMMForArrayCopy + -XX:+UseXmmI2D + -XX:+UseXmmI2F + -XX:+UseXmmLoadAndClearUpper + -XX:+UseXmmRegToRegMoveAll + -XX:+EliminateLocks + -XX:+DoEscapeAnalysis + -XX:+AlignVector + -XX:+OptimizeFill + -XX:+EnableVectorSupport + -XX:+UseCharacterCompareIntrinsics + -XX:+UseCopySignIntrinsic + -XX:+UseVectorStubs + -XX:UseAVX=2 + -XX:UseSSE=4 + -XX:+UseFastJNIAccessors + -XX:+UseInlineCaches + -XX:+SegmentedCodeCache + -Djdk.nio.maxCachedBufferSize=262144 + -Djdk.graal.UsePriorityInlining=true + -Djdk.graal.Vectorization=true + -Djdk.graal.OptDuplication=true + -Djdk.graal.DetectInvertedLoopsAsCounted=true + -Djdk.graal.LoopInversion=true + -Djdk.graal.VectorizeHashes=true + -Djdk.graal.EnterprisePartialUnroll=true + -Djdk.graal.VectorizeSIMD=true + -Djdk.graal.StripMineNonCountedLoops=true + -Djdk.graal.SpeculativeGuardMovement=true + -Djdk.graal.TuneInlinerExploration=1 + -Djdk.graal.LoopRotation=true + -Djdk.graal.CompilerConfiguration=enterprise + ''; + }; + + systemd.services.minecraft = { + description = "Minecraft Java Edition server"; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + + path = [ pkgs.screen ]; + script = "screen -dmS minecraft -- ${lib.getExe inputs.nixpkgs-pin.legacyPackages.${pkgs.system}.graalvm-ce} @/etc/minecraft/java21_args -jar server.jar nogui"; + + serviceConfig = { + User = "minecraft"; + Group = "minecraft"; + WorkingDirectory = "/var/lib/minecraft/vanilla"; + Type = "forking"; + Restart = "on-failure"; + TimerSlackNSec = "5ms"; + + # very necessary and sane hardening for a private minecraft server + CapabilityBoundingSet = [ "" ]; + DeviceAllow = [ "" ]; + DevicePolicy = "strict"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" ]; + UMask = "0027"; + }; + }; +}