···
+
{ config, lib, pkgs, ... }:
+
cfg = config.services.mchprs;
+
settingsFormat = pkgs.formats.toml { };
+
whitelistFile = pkgs.writeText "whitelist.json"
+
(mapAttrsToList (n: v: { name = n; uuid = v; }) cfg.whitelist.list));
+
(removeAttrs cfg.settings [ "address" "port" ]) //
+
bind_address = cfg.settings.address + ":" + toString cfg.settings.port;
+
whitelist = cfg.whitelist.enable;
+
configTomlFile = settingsFormat.generate "Config.toml" configToml;
+
enable = mkEnableOption "MCHPRS";
+
declarativeSettings = mkOption {
+
Whether to use a declarative configuration for MCHPRS.
+
declarativeWhitelist = mkOption {
+
Whether to use a declarative whitelist.
+
The options {option}`services.mchprs.whitelist.list`
+
will be applied if and only if set to `true`.
+
default = "/var/lib/mchprs";
+
Directory to store MCHPRS database and other state/data files.
+
openFirewall = mkOption {
+
Whether to open ports in the firewall for the server.
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
maxRuntime = mkOption {
+
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.
+
defaultText = literalExpression "pkgs.mchprs";
+
description = mdDoc "Version of MCHPRS to run.";
+
type = types.submodule {
+
freeformType = settingsFormat.type;
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
Address for the server.
+
Please use enclosing square brackets when using ipv6.
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
default = "Minecraft High Performance Redstone Server";
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
chat_format = mkOption {
+
default = "<{username}> {message}";
+
How to format chat message interpolating `username`
+
and `message` with curly braces.
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
max_players = mkOption {
+
type = types.ints.positive;
+
Maximum number of simultaneous players.
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
view_distance = mkOption {
+
type = types.ints.positive;
+
Maximal distance (in chunks) between players and loaded chunks.
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
bungeecord = mkOption {
+
Enable compatibility with
+
[BungeeCord](https://github.com/SpigotMC/BungeeCord).
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
Mimic the verification and directory layout used by the
+
Open Redstone Engineers
+
[Schemati plugin](https://github.com/OpenRedstoneEngineers/Schemati).
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
block_in_hitbox = mkOption {
+
Allow placing blocks inside of players
+
(hitbox logic is simplified).
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
auto_redpiler = mkOption {
+
Use redpiler automatically.
+
{option}`services.mchprs.declarativeSettings` is `true`.
+
Configuration for MCHPRS via `Config.toml`.
+
See https://github.com/MCHPR/MCHPRS/blob/master/README.md for documentation.
+
Whether or not the whitelist (in `whitelist.json`) shoud be enabled.
+
Only has effect when {option}`services.mchprs.declarativeSettings` is `true`.
+
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";
+
types.attrsOf minecraftUUID;
+
example = literalExpression ''
+
username1 = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
+
username2 = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy";
+
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 {
+
description = "MCHPRS service user";
+
users.groups.mchprs = { };
+
systemd.services.mchprs = {
+
description = "MCHPRS Service";
+
wantedBy = [ "multi-user.target" ];
+
after = [ "network.target" ];
+
ExecStart = "${lib.getExe cfg.package}";
+
RuntimeMaxSec = cfg.maxRuntime;
+
WorkingDirectory = cfg.dataDir;
+
StandardOutput = "journal";
+
StandardError = "journal";
+
CapabilityBoundingSet = [ "" ];
+
LockPersonality = true;
+
MemoryDenyWriteExecute = true;
+
ProtectControlGroups = true;
+
ProtectHostname = true;
+
ProtectKernelLogs = true;
+
ProtectKernelModules = true;
+
ProtectKernelTunables = true;
+
ProtectProc = "invisible";
+
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+
RestrictNamespaces = true;
+
RestrictRealtime = true;
+
RestrictSUIDSGID = true;
+
SystemCallArchitectures = "native";
+
(if cfg.declarativeSettings then ''
+
if [ -e .declarativeSettings ]; then
+
# Settings were declarative before, no need to back up anything
+
cp -f ${configTomlFile} Config.toml
+
# 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" \
+
if [ -e .declarativeSettings ]; then
+
rm .declarativeSettings
+
'') + (if cfg.declarativeWhitelist then ''
+
if [ -e .declarativeWhitelist ]; then
+
# Whitelist was declarative before, no need to back up anything
+
ln -sf ${whitelistFile} whitelist.json
+
# 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
+
if [ -e .declarativeWhitelist ]; then
+
rm .declarativeWhitelist
+
networking.firewall = mkIf (cfg.declarativeSettings && cfg.openFirewall) {
+
allowedUDPPorts = [ cfg.settings.port ];
+
allowedTCPPorts = [ cfg.settings.port ];
+
meta.maintainers = with maintainers; [ gdd ];