diff --git a/flake.lock b/flake.lock index d2140c4..33e3c75 100644 --- a/flake.lock +++ b/flake.lock @@ -999,8 +999,8 @@ "secret": { "flake": false, "locked": { - "lastModified": 1689425916, - "narHash": "sha256-lQbVxpynVJa9PMIACISoo1TCWbjF5zy4OXqB+lXWE34=", + "lastModified": 1689698765, + "narHash": "sha256-K1mWUDZ4MTzHLf2xB59TgNRj/IzbNed/6uaglXJzF2o=", "path": "/home/main/dotfiles2/secret", "type": "path" }, diff --git a/flake.nix b/flake.nix index 00af377..fa488e6 100644 --- a/flake.nix +++ b/flake.nix @@ -71,6 +71,8 @@ nixng/containers/gitea nixng/containers/hydra nixng/containers/syncthing + nixng/containers/minecraft/vanilla + nixng/containers/minecraft/ftb-infinity overlays/udp-over-tcp.nix overlays/emacsclient-remote diff --git a/nixng/containers/minecraft/ftb-infinity/default.nix b/nixng/containers/minecraft/ftb-infinity/default.nix new file mode 100644 index 0000000..268ea7f --- /dev/null +++ b/nixng/containers/minecraft/ftb-infinity/default.nix @@ -0,0 +1,28 @@ +{ inputs, ... }: +{ + flake.nixngConfigurations.minecraft-ftb-infinity = inputs.nixng.nglib.makeSystem { + system = "x86_64-linux"; + name = "nixng-minecraft"; + inherit (inputs) nixpkgs; + config = + { pkgs, lib, ... }: + { + disabledModules = [ "${inputs.nixng}/modules/services/minecraft.nix" ]; + imports = [ ../../../modules/minecraft-forge.nix ../../../modules/minecraft.nix ]; + dumb-init = { + enable = true; + type.services = {}; + }; + + services.minecraft.forge = { + enable = true; + + modpackId = 23; + versionId = 99; + modpacksChHash = "sha256-wlOcy+Ju81WxJ/z14rslMy3WH+wQdcIZylT7Z3qqJpQ="; + + eulaAccept = true; + }; + }; + }; +} diff --git a/nixng/containers/minecraft/vanilla/default.nix b/nixng/containers/minecraft/vanilla/default.nix new file mode 100644 index 0000000..9875fc8 --- /dev/null +++ b/nixng/containers/minecraft/vanilla/default.nix @@ -0,0 +1,27 @@ +{ inputs, ... }: +{ + flake.nixngConfigurations.minecraft-vanilla = inputs.nixng.nglib.makeSystem { + system = "x86_64-linux"; + name = "nixng-minecraft"; + inherit (inputs) nixpkgs; + config = + { pkgs, lib, nglib, ... }: + { + disabledModules = [ "${inputs.nixng}/modules/services/minecraft.nix" ]; + imports = [ ../../../modules/minecraft-forge.nix ../../../modules/minecraft.nix ]; + dumb-init = { + enable = true; + type.services = {}; + }; + + services.minecraft.vanilla = { + enable = true; + eulaAccept = true; + extraJavaArguments = [ + "-Xmx1024M" + "-Xms1024M" + ]; + }; + }; + }; +} diff --git a/nixng/modules/minecraft-forge.nix b/nixng/modules/minecraft-forge.nix new file mode 100644 index 0000000..21b6c8a --- /dev/null +++ b/nixng/modules/minecraft-forge.nix @@ -0,0 +1,162 @@ +{ pkgs, config, lib, ... }: +with lib; +let + cfg = config.services.minecraft.forge; +in +{ + options.services.minecraft.forge = { + enable = mkEnableOption "Enable Minecraft server service."; + + modpackId = mkOption { + type = types.int; + }; + + versionId = mkOption { + type = types.int; + }; + + modpacksChHash = mkOption { + type = types.str; + }; + + serverPackage = mkOption { + type = types.package; + readOnly = true; + }; + + eulaAccept = mkOption { + type = with types; bool; + description = '' + By changing the setting below to true you are indicating your agreement to Mojang's EULA (https://account.mojang.com/documents/minecraft_eula). + ''; + default = false; + }; + + extraJavaArguments = mkOption { + type = with types; listOf str; + default = []; + }; + }; + + config = mkIf cfg.enable { + + services.minecraft.forge.serverPackage = + let + forgeFod = + pkgs.stdenv.mkDerivation { + pname = "minecraft"; + version = "unknown"; + + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + outputHash = cfg.modpacksChHash; + + buildInputs = with pkgs; [ unzip curl which cacert ]; + + phases = [ "fetchPhase" "installPhase" "fixupPhase "]; + + fetchPhase = '' + curl https://api.modpacks.ch/public/modpack/${toString cfg.modpackId}/${toString cfg.versionId}/server/linux -o modpacks.ch # fuck creeperhost + chmod +x modpacks.ch + ''; + + installPhase = '' + ./modpacks.ch ${toString cfg.modpackId} ${toString cfg.versionId} --auto --nojava --path $out + ''; + + fixupPhase = '' + # delete useless non-reproducible data that we really don't need. A less "shotgun" cleaning is possible + rm $out/version.json + ''; + }; + in + pkgs.stdenv.mkDerivation { + pname = "minecraft"; + version = "unknown"; + + phases = [ "installPhase" ]; + + installPhase = '' + mkdir -p $out/bin + + cp ${pkgs.writeShellScript "server.sh" '' + export PATH=${makeBinPath (with pkgs; [ coreutils findutils bash ])}:$PATH + export _path=$PWD + echo $0 + + echo $rw_paths + function linkFile() + { + _rw_paths=${"( " + lib.concatMapStringsSep " " (x: ''"${x}"'') [ "config" "modpack/gamemodes.json" ] + " )"} + _ignore_paths=${"( " + lib.concatMapStringsSep " " (x: ''"${x}"'') [ "start.sh" ] + " )"} + + echo $1 | grep MrTJP + + ignore=0 + for ignore_path in ''${_ignore_paths[@]} ; do + if [ "''${1##ignore_path}" != "$1" ] || [ "$ignore_path" = "$1" ] ; then + ignore=1 + break + fi + done + + if [ -f "$1" ] || [ $ignore = 1 ] ; then + return + fi + mkdir -p "$_path/$(dirname "$1")" + + copy=0 + for rw_path in ''${_rw_paths[@]} ; do + if [ "''${1##$rw_path}" != "$1" ] || [ "$rw_path" = "$1" ] ; then + copy=1 + break + fi + done + + if [ "$copy" = 1 ] ; then + cp --no-preserve=mode,ownership "${forgeFod}/$1" "$_path/$1" + else + ln -s "${forgeFod}/$1" "$_path/$1" + fi + } + export -f linkFile + + echo $_path + if [ "$_path" = "" ] || ! [ -d "$_path" ] ; then + echo "invalid path" + exit 1 + fi + + find $_path -type l -lname '/nix/store/*' -delete + find $_path -type d -empty -delete + + find ${forgeFod} -type f -printf '%P\n' | tr '\n' '\0' | xargs -0 -I {} sh -c 'linkFile "$1"' sh {} # mkdir -p "$_path/$(dirname "$1")" ; ln -s "${forgeFod}/$1" "$_path/$1" + + ln -s ${pkgs.writeShellScript "start.sh" '' + ${lib.getExe pkgs.jdk8} $(cat ${forgeFod}/start.sh | grep -e "java" -e jar | sed 's/^"java" \(.*\) -jar .*$/\1/') "$@" -jar forge-*.jar + ''} $_path/start.sh + + $_path/start.sh + ''} $out/bin/server + ''; + }; + + init.services.minecraft-forge = { + script = pkgs.writeShellScript "minecraft-run" '' + set -xe + + mkdir -p /var/lib/minecraft/forge + cd /var/lib/minecraft/forge + echo "eula=true" > eula.txt + ${cfg.serverPackage}/bin/server ${concatMapStringsSep " " (x: ''"${x}"'') cfg.extraJavaArguments} + ''; + enabled = true; + }; + + assertions = [ + { assertion = cfg.eulaAccept; + message = "You must accept the EULA"; + } + ]; + }; +} diff --git a/nixng/modules/minecraft.nix b/nixng/modules/minecraft.nix new file mode 100644 index 0000000..156356f --- /dev/null +++ b/nixng/modules/minecraft.nix @@ -0,0 +1,78 @@ +{ pkgs, config, lib, ... }: +with lib; +let + cfg = config.services.minecraft.vanilla; +in +{ + options.services.minecraft.vanilla = { + enable = mkEnableOption "Enable Minecraft server service."; + + serverPackage = mkOption { + type = types.package; + readOnly = true; + }; + + eulaAccept = mkOption { + type = with types; bool; + description = '' + By changing the setting below to true you are indicating your agreement to Mojang's EULA (https://account.mojang.com/documents/minecraft_eula). + ''; + default = false; + }; + + extraJavaArguments = mkOption { + type = with types; listOf str; + default = []; + }; + }; + + config = mkIf cfg.enable { + + services.minecraft.vanilla.serverPackage = + pkgs.stdenv.mkDerivation { + pname = "minecraft"; + version = "unknown"; + + src = pkgs.fetchurl { + url = "https://piston-data.mojang.com/v1/objects/84194a2f286ef7c14ed7ce0090dba59902951553/server.jar"; + hash = "sha256-RIsU/6VxKZ7Sk59dgG4dudHhRLcD+ki32Ab0wv00Tik="; + executable = true; + }; + + phases = [ "installPhase" ]; + + installPhase = '' + mkdir -p $out/bin + + ${lib.getExe pkgs.jdk17} -jar $src --initSettings + mkdir -p $out/share + cp server.properties $out/share/ + + cp ${pkgs.writeShellScript "server.sh" '' + [ -f server.properties ] || cp @out@/share/server.properties . + ${lib.getExe pkgs.jdk17} "$@" -jar @src@ + ''} $out/bin/server + substituteInPlace $out/bin/server --subst-var src --subst-var out + ''; + }; + + init.services.minecraft-vanilla = { + script = pkgs.writeShellScript "minecraft-run" '' + set -xe + + mkdir -p /var/lib/minecraft/vanilla + cd /var/lib/minecraft/vanilla + echo "eula=true" > eula.txt + ${cfg.serverPackage}/bin/server ${concatMapStringsSep " " (x: ''"${x}"'') cfg.extraJavaArguments} + ''; + enabled = true; + shutdownOnExit = true; + }; + + assertions = [ + { assertion = cfg.eulaAccept; + message = "You must accept the EULA"; + } + ]; + }; +} diff --git a/nixos/systems/blowhole/default.nix b/nixos/systems/blowhole/default.nix index 439c8b1..023930d 100644 --- a/nixos/systems/blowhole/default.nix +++ b/nixos/systems/blowhole/default.nix @@ -88,6 +88,8 @@ in }; system.stateVersion = "21.05"; + + boot.kernel.sysctl."fs.inotify.max_user_instances" = 256; }); }; } diff --git a/terranix/containers/minecraft/ftb-infinity/default.nix b/terranix/containers/minecraft/ftb-infinity/default.nix new file mode 100644 index 0000000..fec1fd1 --- /dev/null +++ b/terranix/containers/minecraft/ftb-infinity/default.nix @@ -0,0 +1,24 @@ +{ config', pkgs, elib, vars, ... }: +let + inherit (elib) + nfsVolume + nomadJob; +in +{ + resource."nomad_volume"."minecraft-ftb-infinity" = nfsVolume { + access_mode = "single-node-writer"; + volume_name = "minecraft-ftb-infinity"; + server = "blowhole.hosts.in.redalder.org"; + share = "/mnt/kyle/infrastructure/minecraft/ftb-infinity"; + mount_flags = [ "hard" "vers=4.2" "rsize=131072" "wsize=131072" "async" ]; + }; + + resource."nomad_job"."minecraft-ftb-infinity" = nomadJob { + jobspec = ./job.hcl; + vars = { + flake_ref = "${vars.flake_host}?rev=${vars.flake_rev}&ref=${vars.flake_ref}"; + flake_sha = vars.flake_sha; + store_path = config'.flake.nixngConfigurations.minecraft-ftb-infinity.config.system.build.toplevel; + }; + }; +} diff --git a/terranix/containers/minecraft/ftb-infinity/job.hcl b/terranix/containers/minecraft/ftb-infinity/job.hcl new file mode 100644 index 0000000..7c1e125 --- /dev/null +++ b/terranix/containers/minecraft/ftb-infinity/job.hcl @@ -0,0 +1,62 @@ +variable "flake_ref" { + type = string +} + +variable "flake_sha" { + type = string +} + +variable "store_path" { + type = string +} + +job "minecraft-ftb-infinity" { + datacenters = [ "homelab-1" ] + type = "service" + + group "minecraft-vanilla" { + count = 1 + + volume "minecraft-ftb-infinity" { + type = "csi" + source = "minecraft-ftb-infinity" + read_only = false + + attachment_mode = "file-system" + access_mode = "single-node-writer" + } + + network { + mode = "bridge" + port "minecraft" { + static = 25561 + to = 25565 + } + } + + + task "minecraft-ftb-infinity" { + driver = "docker" + + config { + nix_flake_ref = "${var.flake_ref}#nixngConfigurations.minecraft-ftb-infinity.config.system.build.toplevel" + nix_flake_sha = var.flake_sha + nix_flake_store_path = var.store_path + entrypoint = [ "init" ] + + ports = ["minecraft"] + } + + resources { + cpu = 2048 + memory = 4608 + } + + volume_mount { + volume = "minecraft-ftb-infinity" + destination = "/var/lib/minecraft/forge" + read_only = false + } + } + } +} diff --git a/terranix/containers/minecraft/vanilla/default.nix b/terranix/containers/minecraft/vanilla/default.nix new file mode 100644 index 0000000..9baa4b4 --- /dev/null +++ b/terranix/containers/minecraft/vanilla/default.nix @@ -0,0 +1,24 @@ +{ config', pkgs, elib, vars, ... }: +let + inherit (elib) + nfsVolume + nomadJob; +in +{ + resource."nomad_volume"."minecraft-vanilla" = nfsVolume { + access_mode = "single-node-writer"; + volume_name = "minecraft-vanilla"; + server = "blowhole.hosts.in.redalder.org"; + share = "/mnt/kyle/infrastructure/minecraft/vanilla"; + mount_flags = [ "hard" "vers=4.2" "rsize=131072" "wsize=131072" "async" ]; + }; + + resource."nomad_job"."minecraft-vanilla" = nomadJob { + jobspec = ./job.hcl; + vars = { + flake_ref = "${vars.flake_host}?rev=${vars.flake_rev}&ref=${vars.flake_ref}"; + flake_sha = vars.flake_sha; + store_path = config'.flake.nixngConfigurations.minecraft-vanilla.config.system.build.toplevel; + }; + }; +} diff --git a/terranix/containers/minecraft/vanilla/job.hcl b/terranix/containers/minecraft/vanilla/job.hcl new file mode 100644 index 0000000..162fac6 --- /dev/null +++ b/terranix/containers/minecraft/vanilla/job.hcl @@ -0,0 +1,62 @@ +variable "flake_ref" { + type = string +} + +variable "flake_sha" { + type = string +} + +variable "store_path" { + type = string +} + +job "minecraft-vanilla" { + datacenters = [ "homelab-1" ] + type = "service" + + group "minecraft-vanilla" { + count = 1 + + volume "minecraft-vanilla" { + type = "csi" + source = "minecraft-vanilla" + read_only = false + + attachment_mode = "file-system" + access_mode = "single-node-writer" + } + + network { + mode = "bridge" + port "minecraft" { + static = 25560 + to = 25565 + } + } + + + task "minecraft-vanilla" { + driver = "docker" + + config { + nix_flake_ref = "${var.flake_ref}#nixngConfigurations.minecraft-vanilla.config.system.build.toplevel" + nix_flake_sha = var.flake_sha + nix_flake_store_path = var.store_path + entrypoint = [ "init" ] + + ports = ["minecraft"] + } + + resources { + cpu = 512 + memory = 1280 + } + + volume_mount { + volume = "minecraft-vanilla" + destination = "/var/lib/minecraft/vanilla" + read_only = false + } + } + } +} diff --git a/terranix/containers/syncthing/default.nix b/terranix/containers/syncthing/default.nix index e3c52fa..e0570f7 100644 --- a/terranix/containers/syncthing/default.nix +++ b/terranix/containers/syncthing/default.nix @@ -19,7 +19,7 @@ in access_mode = "single-node-writer"; volume_name = "syncthing-storage"; server = "blowhole.hosts.in.redalder.org"; - share = sharePrefix + "/data"; + share = sharePrefix + "/storage"; mount_flags = [ "hard" "vers=4.2" "rsize=131072" "wsize=131072" "async" ]; }; @@ -27,7 +27,7 @@ in access_mode = "single-node-writer"; volume_name = "syncthing-config"; server = "blowhole.hosts.in.redalder.org"; - share = sharePrefix + "/data"; + share = sharePrefix + "/config"; mount_flags = [ "hard" "vers=4.2" "rsize=131072" "wsize=131072" "async" ]; }; diff --git a/terranix/default.nix b/terranix/default.nix index d9863f9..f4ccb96 100644 --- a/terranix/default.nix +++ b/terranix/default.nix @@ -101,6 +101,16 @@ in source = ./containers/nfs-csi; }; + module."minecraft-vanilla" = elib.terraformModule { + name = "nfs-csi"; + source = ./containers/minecraft/vanilla; + }; + + module."minecraft-ftb-infinity" = elib.terraformModule { + name = "nfs-csi"; + source = ./containers/minecraft/ftb-infinity; + }; + module."altra" = elib.terraformModule { name = "altra"; source = ./altra.nix;