nixos/xonotic: init

Changed files
+199
nixos
modules
services
games
+1
nixos/modules/module-list.nix
···
./services/games/quake3-server.nix
./services/games/teeworlds.nix
./services/games/terraria.nix
+
./services/games/xonotic.nix
./services/hardware/acpid.nix
./services/hardware/actkbd.nix
./services/hardware/argonone.nix
+198
nixos/modules/services/games/xonotic.nix
···
+
{ config
+
, pkgs
+
, lib
+
, ...
+
}:
+
+
let
+
cfg = config.services.xonotic;
+
+
serverCfg = pkgs.writeText "xonotic-server.cfg" (
+
toString cfg.prependConfig
+
+ "\n"
+
+ builtins.concatStringsSep "\n" (
+
lib.mapAttrsToList (key: option:
+
let
+
escape = s: lib.escape [ "\"" ] s;
+
quote = s: "\"${s}\"";
+
+
toValue = x: quote (escape (toString x));
+
+
value = (if lib.isList option then
+
builtins.concatStringsSep
+
" "
+
(builtins.map (x: toValue x) option)
+
else
+
toValue option
+
);
+
in
+
"${key} ${value}"
+
) cfg.settings
+
)
+
+ "\n"
+
+ toString cfg.appendConfig
+
);
+
in
+
+
{
+
options.services.xonotic = {
+
enable = lib.mkEnableOption (lib.mdDoc "Xonotic dedicated server");
+
+
package = lib.mkPackageOption pkgs "xonotic-dedicated" {};
+
+
openFirewall = lib.mkOption {
+
type = lib.types.bool;
+
default = false;
+
description = lib.mdDoc ''
+
Open the firewall for TCP and UDP on the specified port.
+
'';
+
};
+
+
dataDir = lib.mkOption {
+
type = lib.types.path;
+
readOnly = true;
+
default = "/var/lib/xonotic";
+
description = lib.mdDoc ''
+
Data directory.
+
'';
+
};
+
+
settings = lib.mkOption {
+
description = lib.mdDoc ''
+
Generates the `server.cfg` file. Refer to [upstream's example][0] for
+
details.
+
+
[0]: https://gitlab.com/xonotic/xonotic/-/blob/master/server/server.cfg
+
'';
+
default = {};
+
type = lib.types.submodule {
+
freeformType = with lib.types; let
+
scalars = oneOf [ singleLineStr int float ];
+
in
+
attrsOf (oneOf [ scalars (nonEmptyListOf scalars) ]);
+
+
options.sv_public = lib.mkOption {
+
type = lib.types.int;
+
default = 0;
+
example = [ (-1) 1 ];
+
description = lib.mdDoc ''
+
Controls whether the server will be publicly listed.
+
'';
+
};
+
+
options.hostname = lib.mkOption {
+
type = lib.types.singleLineStr;
+
default = "Xonotic $g_xonoticversion Server";
+
description = lib.mdDoc ''
+
The name that will appear in the server list. `$g_xonoticversion`
+
gets replaced with the current version.
+
'';
+
};
+
+
options.sv_motd = lib.mkOption {
+
type = lib.types.singleLineStr;
+
default = "";
+
description = lib.mdDoc ''
+
Text displayed when players join the server.
+
'';
+
};
+
+
options.sv_termsofservice_url = lib.mkOption {
+
type = lib.types.singleLineStr;
+
default = "";
+
description = lib.mdDoc ''
+
URL for the Terms of Service for playing on your server.
+
'';
+
};
+
+
options.maxplayers = lib.mkOption {
+
type = lib.types.int;
+
default = 16;
+
description = lib.mdDoc ''
+
Number of player slots on the server, including spectators.
+
'';
+
};
+
+
options.net_address = lib.mkOption {
+
type = lib.types.singleLineStr;
+
default = "0.0.0.0";
+
description = lib.mdDoc ''
+
The address Xonotic will listen on.
+
'';
+
};
+
+
options.port = lib.mkOption {
+
type = lib.types.port;
+
default = 26000;
+
description = lib.mdDoc ''
+
The port Xonotic will listen on.
+
'';
+
};
+
};
+
};
+
+
# Still useful even though we're using RFC 42 settings because *some* keys
+
# can be repeated.
+
appendConfig = lib.mkOption {
+
type = with lib.types; nullOr lines;
+
default = null;
+
description = lib.mdDoc ''
+
Literal text to insert at the end of `server.cfg`.
+
'';
+
};
+
+
# Certain changes need to happen at the beginning of the file.
+
prependConfig = lib.mkOption {
+
type = with lib.types; nullOr lines;
+
default = null;
+
description = lib.mdDoc ''
+
Literal text to insert at the start of `server.cfg`.
+
'';
+
};
+
};
+
+
config = lib.mkIf cfg.enable {
+
systemd.services.xonotic = {
+
description = "Xonotic server";
+
wantedBy = [ "multi-user.target" ];
+
+
environment = {
+
# Required or else it tries to write the lock file into the nix store
+
HOME = cfg.dataDir;
+
};
+
+
serviceConfig = {
+
DynamicUser = true;
+
User = "xonotic";
+
StateDirectory = "xonotic";
+
ExecStart = "${cfg.package}/bin/xonotic-dedicated";
+
+
# Symlink the configuration from the nix store to where Xonotic actually
+
# looks for it
+
ExecStartPre = [
+
"${pkgs.coreutils}/bin/mkdir -p ${cfg.dataDir}/.xonotic/data"
+
''
+
${pkgs.coreutils}/bin/ln -sf ${serverCfg} \
+
${cfg.dataDir}/.xonotic/data/server.cfg
+
''
+
];
+
+
# Cargo-culted from search results about writing Xonotic systemd units
+
ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
+
+
Restart = "on-failure";
+
RestartSec = 10;
+
StartLimitBurst = 5;
+
};
+
};
+
+
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [
+
cfg.settings.port
+
];
+
networking.firewall.allowedUDPPorts = lib.mkIf cfg.openFirewall [
+
cfg.settings.port
+
];
+
};
+
+
meta.maintainers = with lib.maintainers; [ CobaltCause ];
+
}