{ lib, pkgs, hostInfo, dsl, self, ... }: let inherit (dsl) mkContainer mkService; inherit (hostInfo.paths) data; mkMcTrait = { jdk, dataPath, extraPackages ? [ ], }: { resources.fs."/data" = { hostPath = dataPath; isReadOnly = false; }; users = [ { name = "runner"; uid = 1000; } ]; containerConfig = { pkgs, ... }: { environment.systemPackages = [ jdk pkgs.bash ] ++ extraPackages; systemd.services.minecraft = mkService { description = "Minecraft server"; wantedBy = [ "multi-user.target" ]; after = [ "local-fs.target" "container-ready.target" ]; wants = [ "container-ready.target" ]; path = [ jdk pkgs.bash ]; execStart = "${lib.getExe' pkgs.bash "bash"} -c ${ lib.escapeShellArg ( "exec ${lib.getExe' pkgs.dtach "dtach"} -N /run/ct-attach/attach.sock " + "${lib.getExe' pkgs.util-linux "script"} -qfc /data/launch.sh " + ">(exec ${lib.getExe' pkgs.systemd "systemd-cat"} -t minecraft)" ) }"; serviceConfig = { WorkingDirectory = "/data"; User = "runner"; RuntimeDirectory = "ct-attach"; RuntimeDirectoryMode = "0700"; StandardInput = "null"; StandardOutput = "journal"; StandardError = "journal"; ReadWritePaths = [ "/data" ]; }; }; }; }; extractAttrs = l: s: lib.mergeAttrsList (map (f: lib.optionalAttrs (s ? ${f}) { ${f} = s.${f}; }) l); mkMcSet = { dataDir }: servers: lib.listToAttrs ( map ( args@{ name, jdk, autoStart ? false, allowInternet ? true, dataPath ? "${dataDir}/${name}", extraPackages ? [ ], mem ? "6G", cpu ? 2, ... }: lib.nameValuePair "mc-${name}" (mkContainer { name = "mc-${name}"; net.access = lib.optional allowInternet { to = "@internet"; }; net.expose.tcp = [ (args.hopperPort or 25565) ]; svc.autoStart = autoStart; resources = { inherit cpu mem; }; traits = [ (mkMcTrait { inherit jdk dataPath extraPackages; }) ]; miscProperties = self._hopperRegister (extractAttrs [ "hopperSubdomain" "hopperPort" ] args); includedInTests = false; }) ) servers ); jdk8FontPkgs = with pkgs; [ freetype fontconfig dejavu_fonts ]; mcServers = [ { name = "nomifactory"; jdk = pkgs.jdk8; extraPackages = jdk8FontPkgs; hopperSubdomain = "nomi"; hopperPort = 25555; } { name = "monifactory"; jdk = pkgs.jdk21; hopperSubdomain = "moni"; } { name = "rad2"; jdk = pkgs.jdk8; extraPackages = jdk8FontPkgs; } { name = "smp"; jdk = pkgs.jdk17; } { name = "rc4"; jdk = pkgs.jdk17; } { name = "vh"; jdk = pkgs.jdk17; hopperPort = 25555; } { name = "gregblock"; jdk = pkgs.jdk8; extraPackages = jdk8FontPkgs; } { name = "tfg"; jdk = pkgs.jdk17; } { name = "ratgame"; jdk = pkgs.jdk21; } { name = "maidrpg"; jdk = pkgs.jdk17; } { name = "maidsmp"; jdk = pkgs.jdk21; } { name = "maid-event"; jdk = pkgs.jdk21; hopperSubdomain = "maidevent"; dataPath = "${data}/mc/maidevent/speedrun"; } { name = "gtnh"; jdk = pkgs.jdk21; } { name = "turing"; jdk = pkgs.jdk21; } { name = "tfg2"; jdk = pkgs.jdk21; autoStart = true; mem = "10G"; cpu = 8; } { name = "tl"; jdk = pkgs.jdk21; } { name = "botm"; jdk = pkgs.jdk17; } { name = "rogule-build"; jdk = pkgs.jdk21; } { name = "rogule-dev"; jdk = pkgs.jdk21; } ]; in mkMcSet { dataDir = "${data}/mc"; } mcServers