From 19ecc15b5974dda444317b4fdbb738b556201183 Mon Sep 17 00:00:00 2001 From: Infinidoge Date: Wed, 17 Nov 2021 23:32:06 -0500 Subject: [PATCH] modules: restructure modules directory --- modules/{ => devos}/hm-system-defaults.nix | 0 modules/{ => devos}/nix-path.nix | 2 +- .../minecraft-servers/default.nix | 57 +++++++++++ .../minecraft-servers/options.nix | 69 ++++++++++++++ .../minecraft-servers/service.nix | 95 +++++++++++++++++++ modules/{ => functionality}/ssh-tunnel.nix | 0 6 files changed, 222 insertions(+), 1 deletion(-) rename modules/{ => devos}/hm-system-defaults.nix (100%) rename modules/{ => devos}/nix-path.nix (72%) create mode 100644 modules/functionality/minecraft-servers/default.nix create mode 100644 modules/functionality/minecraft-servers/options.nix create mode 100644 modules/functionality/minecraft-servers/service.nix rename modules/{ => functionality}/ssh-tunnel.nix (100%) diff --git a/modules/hm-system-defaults.nix b/modules/devos/hm-system-defaults.nix similarity index 100% rename from modules/hm-system-defaults.nix rename to modules/devos/hm-system-defaults.nix diff --git a/modules/nix-path.nix b/modules/devos/nix-path.nix similarity index 72% rename from modules/nix-path.nix rename to modules/devos/nix-path.nix index 273f67a..ddf7b80 100644 --- a/modules/nix-path.nix +++ b/modules/devos/nix-path.nix @@ -1,7 +1,7 @@ { channel, inputs, ... }: { nix.nixPath = [ "nixpkgs=${channel.input}" - "nixos-config=${../lib/compat/nixos}" + "nixos-config=${../../lib/compat/nixos}" "home-manager=${inputs.home}" ]; } diff --git a/modules/functionality/minecraft-servers/default.nix b/modules/functionality/minecraft-servers/default.nix new file mode 100644 index 0000000..96031f0 --- /dev/null +++ b/modules/functionality/minecraft-servers/default.nix @@ -0,0 +1,57 @@ +{ config, lib, pkgs, ... }@main: + +with lib; + +let + cfg = config.services.minecraft-servers; + + +in +{ + options = (import ./options.nix) main; + + config = mkIf cfg.enable { + users.users.minecraft = { + description = "Minecraft server service user"; + home = cfg.dataDir; + createHome = true; + isSystemUser = true; + group = "minecraft"; + }; + + users.groups.minecraft = { }; + + # systemd.services = mkIf (cfg.enable && cfg.servers != { }) ((import ./service.nix) main cfg); + + }; + + # networking.firewall = let + + # propertyFunc = attrsets.mapAttrsToList (name: value: + # let props = value.serverProperties; + # in (if value.declarative then [ + # (props.server-port or 25565) + # (if props.enable-rcon or false then + # props."rcon.port" or 25575 + # else + # null) + # (if props.enable-query or false then + # props "query.port" or 25565 + # else + # null) + # ] else + # null)) cfg.servers; + + # openedPorts = lists.flatten [ serverPorts queryPorts rconPorts ]; + # in { + # allowedUDPPorts = openedPorts; + # allowedTCPPorts = openedPorts; + # }; + + # assertions = [{ + # assertion = all (i: i.eula == true) (attrValues cfg.servers); + # message = "You must agree to Mojangs EULA to run minecraft-server." + # + " Read https://account.mojang.com/documents/minecraft_eula and" + # + " set `services.minecraft-servers.servers..eula` to `true` for all servers if you agree."; + # }]; +} diff --git a/modules/functionality/minecraft-servers/options.nix b/modules/functionality/minecraft-servers/options.nix new file mode 100644 index 0000000..799aaf5 --- /dev/null +++ b/modules/functionality/minecraft-servers/options.nix @@ -0,0 +1,69 @@ +{ lib, ... }: +with lib; +{ + services.minecraft-servers = { + enable = mkEnableOption "minecraft servers"; + # TODO: verbose minecraft-servers enable option + + openFirewall = + mkEnableOption "opening the firewall for each server by default"; + # TODO: verbose outer openFirewall option + + dataDir = mkOption { + type = types.path; + default = "/var/lib/minecraft"; + # TODO: verbose dataDir option + }; + + servers = mkOption { + type = types.attrsOf (types.submodule { + enable = mkEnableOption "this minecraft server"; + # TODO: verbose server enable option + + declarative = mkEnableOption "declarative server management"; + # TODO: verbose declarative option + + eula = mkEnableOption "accepting the eula"; + # TODO: verbose eula option + + openFirewall = mkOption { + type = types.bool; + default = true; # cfg.openFirewall; + # TODO: openFirewall description + }; + + jvmOpts = mkOption { + type = types.separatedString " "; + default = "-Xmx2048M -Xms2048M"; + # TODO: verbose jvmOpts option + }; + + package = mkOption { + type = types.package; + default = pkgs.minecraft-server; + # TODO: verbose package option + }; + + whitelist = mkOption { + type = + let + minecraftUUID = types.strMatching + "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + // { + description = "Minecraft UUID"; + }; + in + types.attrsOf minecraftUUID; + default = { }; + # TODO: verbose whitelist option + }; + + serverProperties = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { server-port = 25565; }; + # TODO: verbose serverProperties option + }; + }); + }; + }; +} diff --git a/modules/functionality/minecraft-servers/service.nix b/modules/functionality/minecraft-servers/service.nix new file mode 100644 index 0000000..d74d584 --- /dev/null +++ b/modules/functionality/minecraft-servers/service.nix @@ -0,0 +1,95 @@ +{ pkgs, lib, ... }: cfg: + +with lib; +let + eulaFile = builtins.toFile "eula.txt" '' + # eula.txt managed by NixOS Configuration + eula=true + ''; + + whitelistFile = server: + pkgs.writeText "whitelist.json" (builtins.toJSON (mapAttrsToList + (n: v: { + name = n; + uuid = v; + }) + server.whitelist)); + + + serverPropertiesFile = + let + cfgToString = v: if builtins.isBool v then boolToString v else toString v; + in + (server: + pkgs.writeText "server.properties" ('' + # server.properties managed by NixOS configuration + '' + concatStringsSep "\n" + (mapAttrsToList (n: v: "${n}=${cfgToString v}") server.serverProperties))); + + tmux = "${getBin pkgs.tmux}/bin/tmux"; + + stopScript = name: + pkgs.writeScript "minecraft-stop" '' + #!${pkgs.runtimeShell} + + if ! [ -d "/proc/$1" ]; then + exit 0 + fi + + ${tmux} -S ${cfg.dataDir}/${name}.sock send-keys Enter stop Enter + ${getBin pkgs.coreutils}/bin/tail --pid-"$1" -f /dev/null + ''; + + mkService = (name: inst: nameValuePair + ("minecraft-server-${name}") + ({ + description = "Minecraft Server Service: ${name}"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + ExecStart = '' + ${tmux} -S ${cfg.dataDir}/${name}.sock new \ + -d ${inst.package}/bin/minecraft-server ${inst.jvmOpts} + ''; + ExecStop = "${stopScript name} $MAINPID"; + Restart = "always"; + Type = "forking"; + GuessMainPIP = true; + User = "minecraft"; + WorkingDirectory = "${cfg.dataDir}/${name}"; + }; + + preStart = '' + ln -sf ${eulaFile} eula.txt + '' + (if inst.declarative then '' + if [ -e .declarative ]; then + # Was declarative before, no need to back up anything + ln -sf ${whitelistFile inst} whitelist.json + cp -f ${serverPropertiesFile inst} server.properties + else + # Declarative for the first time, backup stateful files + ln -sb --suffix=.stateful ${whitelistFile inst} whitelist.json + cp -b --suffix=.stateful ${ + serverPropertiesFile inst + } server.properties + # server.properties must have write permissions, because every time + # the server starts it first parses the file and then regenerates it.. + chmod +w server.properties + echo "Autogenerated file that signifies that this server configuration is managed declaratively by NixOS" \ + > .declarative + fi + '' else '' + if [ -e .declarative ]; then + rm .declarative + fi + ''); + + postStart = '' + ${pkgs.coreutils}/bin/chmod 660 ${cfg.dataDir}/${name}.sock + ${pkgs.coreutils}/bin/chgrp minecraft ${cfg.dataDir}/${name}.sock + ''; + }) + ); +in +flip mapAttrs' cfg.servers mkService diff --git a/modules/ssh-tunnel.nix b/modules/functionality/ssh-tunnel.nix similarity index 100% rename from modules/ssh-tunnel.nix rename to modules/functionality/ssh-tunnel.nix