summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services/games
diff options
context:
space:
mode:
authorgabriel-doriath-dohler <gabriel.doriath.dohler@ens.fr>2023-07-02 23:59:59 +0000
committergabriel-doriath-dohler <gabriel.doriath.dohler@ens.fr>2023-07-02 23:59:59 +0000
commit04c830db01dc5ca25290716ae4e6049bb8074e9b (patch)
treefefdbb6e2f45918077ff03e2fc9a1ab5bcc92f41 /nixos/modules/services/games
parent4f822ac9fd94b9a63b008e58eff17785f26f6517 (diff)
nixos/mchprs: init module
Co-authored-by: Ryan Lahfa <masterancpp@gmail.com>
Diffstat (limited to 'nixos/modules/services/games')
-rw-r--r--nixos/modules/services/games/mchprs.nix341
1 files changed, 341 insertions, 0 deletions
diff --git a/nixos/modules/services/games/mchprs.nix b/nixos/modules/services/games/mchprs.nix
new file mode 100644
index 000000000000..a65001b0b3e2
--- /dev/null
+++ b/nixos/modules/services/games/mchprs.nix
@@ -0,0 +1,341 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.mchprs;
+ settingsFormat = pkgs.formats.toml { };
+
+ whitelistFile = pkgs.writeText "whitelist.json"
+ (builtins.toJSON
+ (mapAttrsToList (n: v: { name = n; uuid = v; }) cfg.whitelist.list));
+
+ configToml =
+ (removeAttrs cfg.settings [ "address" "port" ]) //
+ {
+ bind_address = cfg.settings.address + ":" + toString cfg.settings.port;
+ whitelist = cfg.whitelist.enable;
+ };
+
+ configTomlFile = settingsFormat.generate "Config.toml" configToml;
+in
+{
+ options = {
+ services.mchprs = {
+ enable = mkEnableOption "MCHPRS";
+
+ declarativeSettings = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc ''
+ Whether to use a declarative configuration for MCHPRS.
+ '';
+ };
+
+ declarativeWhitelist = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc ''
+ Whether to use a declarative whitelist.
+ The options {option}`services.mchprs.whitelist.list`
+ will be applied if and only if set to `true`.
+ '';
+ };
+
+ dataDir = mkOption {
+ type = types.path;
+ default = "/var/lib/mchprs";
+ description = mdDoc ''
+ Directory to store MCHPRS database and other state/data files.
+ '';
+ };
+
+ openFirewall = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc ''
+ Whether to open ports in the firewall for the server.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ maxRuntime = mkOption {
+ type = types.str;
+ default = "infinity";
+ example = "7d";
+ description = mdDoc ''
+ Automatically restart the server after
+ {option}`services.mchprs.maxRuntime`.
+ The time span format is described here:
+ https://www.freedesktop.org/software/systemd/man/systemd.time.html#Parsing%20Time%20Spans.
+ If `null`, then the server is not restarted automatically.
+ '';
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.mchprs;
+ defaultText = literalExpression "pkgs.mchprs";
+ description = mdDoc "Version of MCHPRS to run.";
+ };
+
+ settings = mkOption {
+ type = types.submodule {
+ freeformType = settingsFormat.type;
+
+ options = {
+ port = mkOption {
+ type = types.port;
+ default = 25565;
+ description = mdDoc ''
+ Port for the server.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ address = mkOption {
+ type = types.str;
+ default = "0.0.0.0";
+ description = mdDoc ''
+ Address for the server.
+ Please use enclosing square brackets when using ipv6.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ motd = mkOption {
+ type = types.str;
+ default = "Minecraft High Performance Redstone Server";
+ description = mdDoc ''
+ Message of the day.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ chat_format = mkOption {
+ type = types.str;
+ default = "<{username}> {message}";
+ description = mdDoc ''
+ How to format chat message interpolating `username`
+ and `message` with curly braces.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ max_players = mkOption {
+ type = types.ints.positive;
+ default = 99999;
+ description = mdDoc ''
+ Maximum number of simultaneous players.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ view_distance = mkOption {
+ type = types.ints.positive;
+ default = 8;
+ description = mdDoc ''
+ Maximal distance (in chunks) between players and loaded chunks.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ bungeecord = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc ''
+ Enable compatibility with
+ [BungeeCord](https://github.com/SpigotMC/BungeeCord).
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ schemati = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc ''
+ Mimic the verification and directory layout used by the
+ Open Redstone Engineers
+ [Schemati plugin](https://github.com/OpenRedstoneEngineers/Schemati).
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ block_in_hitbox = mkOption {
+ type = types.bool;
+ default = true;
+ description = mdDoc ''
+ Allow placing blocks inside of players
+ (hitbox logic is simplified).
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ auto_redpiler = mkOption {
+ type = types.bool;
+ default = true;
+ description = mdDoc ''
+ Use redpiler automatically.
+ Only has effect when
+ {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+ };
+ };
+ default = { };
+
+ description = mdDoc ''
+ Configuration for MCHPRS via `Config.toml`.
+ See https://github.com/MCHPR/MCHPRS/blob/master/README.md for documentation.
+ '';
+ };
+
+ whitelist = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc ''
+ Whether or not the whitelist (in `whitelist.json`) shoud be enabled.
+ Only has effect when {option}`services.mchprs.declarativeSettings` is `true`.
+ '';
+ };
+
+ list = 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 = { };
+ example = literalExpression ''
+ {
+ username1 = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
+ username2 = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy";
+ };
+ '';
+ description = mdDoc ''
+ Whitelisted players, only has an effect when
+ {option}`services.mchprs.declarativeWhitelist` is
+ `true` and the whitelist is enabled
+ via {option}`services.mchprs.whitelist.enable`.
+ This is a mapping from Minecraft usernames to UUIDs.
+ You can use <https://mcuuid.net/> to get a
+ Minecraft UUID for a username.
+ '';
+ };
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ users.users.mchprs = {
+ description = "MCHPRS service user";
+ home = cfg.dataDir;
+ createHome = true;
+ isSystemUser = true;
+ group = "mchprs";
+ };
+ users.groups.mchprs = { };
+
+ systemd.services.mchprs = {
+ description = "MCHPRS Service";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+
+ serviceConfig = {
+ ExecStart = "${lib.getExe cfg.package}";
+ Restart = "always";
+ RuntimeMaxSec = cfg.maxRuntime;
+ User = "mchprs";
+ WorkingDirectory = cfg.dataDir;
+
+ StandardOutput = "journal";
+ StandardError = "journal";
+
+ # Hardening
+ CapabilityBoundingSet = [ "" ];
+ DeviceAllow = [ "" ];
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ PrivateDevices = true;
+ PrivateTmp = true;
+ PrivateUsers = true;
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectProc = "invisible";
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ UMask = "0077";
+ };
+
+ preStart =
+ (if cfg.declarativeSettings then ''
+ if [ -e .declarativeSettings ]; then
+
+ # Settings were declarative before, no need to back up anything
+ cp -f ${configTomlFile} Config.toml
+
+ else
+
+ # Declarative settings for the first time, backup stateful files
+ cp -b --suffix=.stateful ${configTomlFile} Config.toml
+
+ echo "Autogenerated file that implies that this server configuration is managed declaratively by NixOS" \
+ > .declarativeSettings
+
+ fi
+ '' else ''
+ if [ -e .declarativeSettings ]; then
+ rm .declarativeSettings
+ fi
+ '') + (if cfg.declarativeWhitelist then ''
+ if [ -e .declarativeWhitelist ]; then
+
+ # Whitelist was declarative before, no need to back up anything
+ ln -sf ${whitelistFile} whitelist.json
+
+ else
+
+ # Declarative whitelist for the first time, backup stateful files
+ ln -sb --suffix=.stateful ${whitelistFile} whitelist.json
+
+ echo "Autogenerated file that implies that this server's whitelist is managed declaratively by NixOS" \
+ > .declarativeWhitelist
+
+ fi
+ '' else ''
+ if [ -e .declarativeWhitelist ]; then
+ rm .declarativeWhitelist
+ fi
+ '');
+ };
+
+ networking.firewall = mkIf (cfg.declarativeSettings && cfg.openFirewall) {
+ allowedUDPPorts = [ cfg.settings.port ];
+ allowedTCPPorts = [ cfg.settings.port ];
+ };
+ };
+
+ meta.maintainers = with maintainers; [ gdd ];
+}