dotfiles

My PC Dotfiles & Website

modules/games/mc-server/default.nix (5081B)


  1## Minecraft Server Configuration ##
  2# ? # Run 'systemctl start minecraft-server-NAME' to start the server
  3# ? # Run 'echo COMMAND > /run/minecraft/NAME.stdin' to run commands
  4{
  5  config,
  6  inputs,
  7  ...
  8}: let
  9  inherit (config.flake.files) path;
 10in {
 11  flake.modules.nixos.mc-server = {
 12    config,
 13    lib,
 14    pkgs,
 15    ...
 16  }: let
 17    inherit
 18      (lib)
 19      concatMap
 20      filter
 21      mkIf
 22      mkMerge
 23      mkOption
 24      types
 25      ;
 26    inherit (pkgs) fetchurl fetchzip linkFarm;
 27
 28    cfg = config.games.mc-servers;
 29    dataDir = "/srv/minecraft";
 30
 31    # Mods
 32    modData = import ./_mods.nix;
 33    mkMods = srv: loader: let
 34      mods = filter (m: !(m ? require) || (m.require == "vc-port" && srv.vc-port != null)) loader.mods;
 35    in
 36      linkFarm "mods" (map (m: {
 37          name = "${m.name}.jar";
 38          path = fetchurl {inherit (m) name url hash;};
 39        })
 40        mods);
 41  in {
 42    imports = [inputs.minecraft.nixosModules.minecraft-servers];
 43
 44    options.games.mc-servers = mkOption {
 45      description = "List of Minecraft Servers";
 46      default = [];
 47      type = types.listOf (
 48        types.submodule (
 49          {config, ...}: {
 50            options = {
 51              name = mkOption {
 52                description = "Unique server name";
 53                type = types.str;
 54                default = config.type;
 55              };
 56
 57              type = mkOption {
 58                description = "Server Type";
 59                type = types.enum [
 60                  "fabric"
 61                  "skyblock"
 62                ];
 63                default = "fabric";
 64              };
 65
 66              memory = mkOption {
 67                description = "Memory (GB) allocated to server";
 68                type = types.int;
 69                default = 12;
 70              };
 71
 72              config = mkOption {
 73                description = "Server Properties";
 74                type = types.attrs;
 75                default = {};
 76              };
 77
 78              port = mkOption {
 79                description = "Main server TCP port";
 80                type = types.int;
 81                default = 25565;
 82              };
 83
 84              vc-port = mkOption {
 85                description = "Port for Simple Voice Chat";
 86                type = with types; nullOr int;
 87                default = null;
 88              };
 89            };
 90          }
 91        )
 92      );
 93    };
 94
 95    config = mkIf (cfg != []) {
 96      system.fs.persist.directories = [dataDir];
 97      disko.devices.zpool.fspool.datasets."data/minecraft" = mkIf (config.system.fs.scheme == "advanced") {
 98        type = "zfs_fs";
 99        mountpoint = "${path.data}${dataDir}";
100        options = {
101          atime = "off";
102          mountpoint = "legacy";
103          recordsize = "32K";
104          "com.sun:auto-snapshot" = "true";
105        };
106      };
107
108      networking.firewall = {
109        allowedTCPPorts = map (srv: srv.port) cfg;
110        allowedUDPPorts = concatMap (srv:
111          if (srv.vc-port != null)
112          then [srv.vc-port]
113          else [])
114        cfg;
115      };
116
117      services.minecraft-servers = {
118        enable = true;
119        inherit dataDir;
120        eula = true;
121        openFirewall = true;
122        managementSystem = {
123          tmux.enable = false;
124          systemd-socket.enable = true;
125        };
126
127        servers = builtins.listToAttrs (
128          map (srv: {
129            inherit (srv) name;
130            value = mkMerge [
131              {
132                enable = true;
133                autoStart = false;
134                serverProperties = srv.config // {server-port = srv.port;};
135                jvmOpts = let
136                  mem = toString srv.memory;
137                in
138                  lib.concatStringsSep " " [
139                    "-Xms${mem}G"
140                    "-Xmx${mem}G"
141                    "-XX:+UseZGC"
142                    "-XX:+AlwaysPreTouch"
143                    "--add-modules=jdk.incubator.vector"
144                    "--enable-native-access=ALL-UNNAMED"
145                  ];
146              }
147
148              ## Fabric Server
149              (mkIf (srv.type == "fabric") {
150                package = pkgs.fabricServers.fabric-26_3.override {jre_headless = pkgs.jdk25_headless;};
151                symlinks.mods = mkMods srv modData.fabric;
152              })
153
154              ## Modded Skyblock Server
155              (mkIf (srv.type == "skyblock") (
156                let
157                  inherit (inputs.minecraft.lib) collectFilesAt;
158
159                  # Ozone Skyblock Reborn 2
160                  modpack = fetchzip {
161                    url = "https://mediafilez.forgecdn.net/files/8061/293/OSR%201.5.4%20-%20Server.zip";
162                    sha256 = "sha256-L9bh+MbKgKeD+RezVkmUWSK7kFiUSZrDyPLp7MrPXAY=";
163                  };
164                in {
165                  package = pkgs.neoforgeServers.neoforge-1_21_1;
166                  files = (collectFilesAt modpack "config") // (collectFilesAt modpack "kubejs");
167                  symlinks = collectFilesAt modpack "mods";
168                }
169              ))
170            ];
171          })
172          cfg
173        );
174      };
175    };
176  };
177}