{ config, lib, pkgs, ... }: with lib; let cfg = config.clerie.minecraft-server; # We don't allow eula=false anyways eulaFile = builtins.toFile "eula.txt" '' # eula.txt managed by NixOS Configuration eula=true ''; generateServerUnit = name: server: ( nameValuePair "minecraft-server-${name}" (mkIf server.enable { description = "Minecraft Server ${name}"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { ExecStart = "${server.package}/bin/minecraft-server ${server.jvmOpts}"; Restart = "always"; WorkingDirectory = if server.dataDir != null then server.dataDir else "/var/lib/minecraft-server-${name}"; StateDirectory = "minecraft-server-${name}"; DynamicUser = true; }; preStart = '' ln -sf ${eulaFile} eula.txt ''; }) ); serverOpts = { config, ... }@moduleAttrs: { options = { enable = mkEnableOption "A shared minecraft hosting service."; dataDir = mkOption { type = with types; nullOr path; default = null; description = '' Directory to store Minecraft database and other state/data files. When null defaulting to /var/lib/minecraft-server-${name} ''; }; package = mkOption { type = types.package; default = pkgs.papermc; defaultText = "pkgs.papermc"; example = literalExample "pkgs.minecraft-server_1_12_2"; description = "Version of minecraft-server to run."; }; jvmOpts = mkOption { type = types.separatedString " "; default = "-Xmx2G -Xms1G"; # 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."; }; }; }; in { options = { clerie.minecraft-server = { servers = mkOption { type = with types; attrsOf (submodule serverOpts); default = {}; }; }; }; config = { systemd.services = (mapAttrs' generateServerUnit cfg.servers); }; }