Skip to content

Commit b8b92d3

Browse files
committed
Add LazyMC Support
1 parent 4ca5164 commit b8b92d3

File tree

2 files changed

+142
-14
lines changed

2 files changed

+142
-14
lines changed

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,3 +503,53 @@ files."white-list.txt" = {
503503
```
504504

505505
generates a legacy `white-list.txt` that is needed for older minecraft versions (< 1.7.6)
506+
507+
#### `servers.<name>.lazymc`
508+
509+
Integrates [lazymc](https://github.com/timvisee/lazymc), putting server to sleep when idle and waking it upon player connection.
510+
When enabled the server's public address is controlled by lazymc, by default 25565. So a new internal `serverProperties.server-port` has to be chosen.
511+
512+
* **`enable`**: `boolean`, default `false`
513+
514+
* **`package`**: `package`, default `pkgs.lazymc`
515+
The `lazymc` package to use. You might have to change lazymc version according to your minecraft server version, for example lazymc v0.2.10 supports Minecraft Java Edition 1.7.2+, while for Minecraft Java Edition 1.20.3+ you'll need lazymc v0.2.11
516+
517+
* **`config`**: `attribute set`, default `{}`
518+
Allows defining and overriding settings in the `lazymc.toml`, for all options see [here](https://github.com/timvisee/lazymc/blob/master/res/lazymc.toml). The auto generated config options are:
519+
* `server.command`: Automatically set to use the server `package` and `jvmOpts`;
520+
* `server.directory`;
521+
* `server.address`: Automatically set to `127.0.0.1:<serverProperties.server-port or 25565>";`
522+
523+
**Firewall**
524+
* When `lazymc.enable = true`, the `openFirewall` option for this server instance will open the port specified in `lazymc.config.public.address` (or 25565), not the internal Minecraft `serverProperties.server-port`.
525+
526+
**Example:**
527+
```nix
528+
{ pkgs, ... }: {
529+
services.minecraft-servers = {
530+
eula = true;
531+
servers.myLazyServer = {
532+
enable = true;
533+
package = pkgs.paperServers.paper-1_18_2;
534+
serverProperties = {
535+
"server-port" = 25566;
536+
"max-tick-time" = -1; # Recommended with lazymc
537+
};
538+
539+
lazymc = {
540+
enable = true;
541+
package = let
542+
# you can use https://lazamar.co.uk/nix-versions/
543+
pkgs-with-lazymc_0_2_10 = import (builtins.fetchTarball {
544+
url = "https://github.com/NixOS/nixpkgs/archive/336eda0d07dc5e2be1f923990ad9fdb6bc8e28e3.tar.gz";
545+
sha256 = "sha256:0v8vnmgw7cifsp5irib1wkc0bpxzqcarlv8mdybk6dck5m7p10lr";
546+
}) { inherit (pkgs) system; };
547+
in pkgs-with-lazymc_0_2_10.lazymc;
548+
config = {
549+
public.address = "0.0.0.0:25565";
550+
};
551+
};
552+
};
553+
};
554+
}
555+
```

modules/minecraft-servers.nix

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ let
151151
let
152152
ms = server.managementSystem;
153153
tmux = "${getBin pkgs.tmux}/bin/tmux";
154+
runCommand =
155+
if server.lazymc.enable then
156+
"${server.lazymc.package}/bin/lazymc start --config lazymc.toml"
157+
else
158+
"${getExe server.package} ${server.jvmOpts}";
154159
in
155160
assert assertMsg (
156161
!(ms.tmux.enable && ms.systemd-socket.enable)
@@ -166,7 +171,7 @@ let
166171
};
167172
hooks = {
168173
start = ''
169-
${tmux} -S ${sock} new -d ${getExe server.package} ${server.jvmOpts}
174+
${tmux} -S ${sock} new -d ${runCommand}
170175
171176
# HACK: PrivateUsers makes every user besides root/minecraft `nobody`, so this restores old tmux behavior
172177
# See https://github.com/Infinidoge/nix-minecraft/issues/5
@@ -176,17 +181,19 @@ let
176181
${pkgs.coreutils}/bin/chmod 660 ${sock}
177182
'';
178183
stop = ''
179-
function server_running {
180-
${tmux} -S ${sock} has-session
181-
}
184+
${optionalString (!server.lazymc.enable) ''
185+
function server_running {
186+
${tmux} -S ${sock} has-session
187+
}
182188
183-
if ! server_running ; then
184-
exit 0
185-
fi
189+
if ! server_running ; then
190+
exit 0
191+
fi
186192
187-
${tmux} -S ${sock} send-keys C-u ${escapeShellArg server.stopCommand} Enter
193+
${tmux} -S ${sock} send-keys C-u ${escapeShellArg server.stopCommand} Enter
188194
189-
while server_running; do sleep 1s; done
195+
while server_running; do sleep 1s; done
196+
''}
190197
'';
191198
};
192199
}
@@ -200,11 +207,11 @@ let
200207
};
201208
hooks = {
202209
start = ''
203-
${getExe server.package} ${server.jvmOpts}
210+
${runCommand}
204211
'';
205212
postStart = "";
206213
stop = ''
207-
${optionalString (server.stopCommand != null) ''
214+
${optionalString (server.stopCommand != null && !server.lazymc.enable) ''
208215
echo ${escapeShellArg server.stopCommand} > ${escapeShellArg (ms.systemd-socket.stdinSocket.path name)}
209216
210217
while kill -0 "$1" 2> /dev/null; do sleep 1s; done
@@ -556,6 +563,35 @@ in
556563
default = { };
557564
example = options.services.minecraft-servers.managementSystem.example;
558565
};
566+
lazymc = {
567+
enable = mkEnableOpt "Puts your Minecraft server to rest when idle, and wakes it up when players connect.";
568+
package = mkOption {
569+
type = types.package;
570+
default = pkgs.lazymc;
571+
defaultText = literalExpression "pkgs.lazymc";
572+
description = "The lazymc package to use.";
573+
};
574+
config = mkOption {
575+
type = types.attrs;
576+
default = { };
577+
description = ''
578+
Configuration for lazymc, mirroring its TOML structure.
579+
Some values like server.command, server.directory and server.address will
580+
be automatically configured by this module when generating lazymc.toml.
581+
582+
See <link xlink:href="https://github.com/timvisee/lazymc/blob/master/res/lazymc.toml"/>
583+
for documentation on these values.
584+
'';
585+
example = literalExpression ''
586+
{
587+
public.address = "0.0.0.0:25565"; # Public port for players
588+
time.sleep_after = 900; # Sleep after 15 minutes
589+
motd.sleeping = "Shhh, the server is napping!";
590+
server.forge = false; # Set to true if this is a Forge server
591+
}
592+
'';
593+
};
594+
};
559595
};
560596
}
561597
)
@@ -566,6 +602,17 @@ in
566602
config = mkIf cfg.enable (
567603
let
568604
servers = filterAttrs (_: cfg: cfg.enable) cfg.servers;
605+
606+
getPublicPort =
607+
_: conf:
608+
if conf.lazymc.enable then
609+
let
610+
addr = conf.lazymc.config.public.address or "0.0.0.0:25565";
611+
portStr = lib.last (lib.splitString ":" addr);
612+
in
613+
lib.toInt portStr
614+
else
615+
conf.serverProperties.server-port or 25565;
569616
in
570617
{
571618
users = {
@@ -598,15 +645,35 @@ in
598645
{
599646
assertion =
600647
let
601-
serverPorts = mapAttrsToList (name: conf: conf.serverProperties.server-port or 25565) (
648+
serverPorts = mapAttrsToList (name: conf: getPublicPort _ conf) (
602649
filterAttrs (_: cfg: cfg.openFirewall) servers
603650
);
604651

605652
counts = map (port: count (x: x == port) serverPorts) (unique serverPorts);
606653
in
607654
lib.all (x: x == 1) counts;
608-
message = "Multiple servers are set to use the same port. Change one to use a different port.";
655+
message = "Multiple servers are set to use the same public port (either through lazymc public.address or server.properties server-port). Change one to use a different port.";
609656
}
657+
(
658+
let
659+
lazymcPortConflicts = filter (x: x.hasConflict) (
660+
mapAttrsToList (name: conf: {
661+
inherit name;
662+
hasConflict =
663+
conf.lazymc.enable && getPublicPort _ conf == (conf.serverProperties.server-port or 25565);
664+
}) servers
665+
);
666+
conflictingServerNames = map (x: x.name) lazymcPortConflicts;
667+
in
668+
{
669+
assertion = lazymcPortConflicts == [ ];
670+
message = ''
671+
Server(s): ${concatStringsSep ", " conflictingServerNames} has the same port set for serverProperties.server-port and lazymc.config.public.address
672+
Please set for example: `serverName.serverProperties.server-port = 25566;`, lazymc's internal server.address will automatically point to it
673+
Lazymc's public.address is "0.0.0.0:25565" by default
674+
'';
675+
}
676+
)
610677
];
611678

612679
warnings = lib.optional (cfg.runDir != options.services.minecraft-servers.runDir.default) ''
@@ -624,7 +691,9 @@ in
624691
# Minecraft and RCON
625692
getTCPPorts =
626693
n: c:
627-
[ c.serverProperties.server-port or 25565 ]
694+
[
695+
(getPublicPort n c)
696+
]
628697
++ (optional (c.serverProperties.enable-rcon or false) (c.serverProperties."rcon.port" or 25575));
629698
# Query
630699
getUDPPorts =
@@ -691,6 +760,15 @@ in
691760
}) conf.operators;
692761
"server.properties".value = conf.serverProperties;
693762
}
763+
// (optionalAttrs conf.lazymc.enable {
764+
"lazymc.toml".value = lib.recursiveUpdate {
765+
server = {
766+
command = "${getExe conf.package} ${conf.jvmOpts}";
767+
directory = ".";
768+
address = "127.0.0.1:${toString conf.serverProperties.server-port or 25565}";
769+
};
770+
} conf.lazymc.config;
771+
})
694772
// conf.files
695773
);
696774

0 commit comments

Comments
 (0)