nix-minecraft icon indicating copy to clipboard operation
nix-minecraft copied to clipboard

Add lazymc (on-demand) functionality to nix-minecraft

Open Yeshey opened this issue 7 months ago • 26 comments

Solves https://github.com/Infinidoge/nix-minecraft/issues/142 This adds the options:

        lazymc = {
          enable = true;
          package = pkgs.lazymc;
          config = { ... };
        };

Under each instance. This makes servers go to sleep when there are no players and wake up when one player tries to join lazymc

servers.<name>.lazymc

Integrates lazymc, putting server to sleep when idle and waking it upon player connection.

  • enable: boolean, default false

  • package: package, default pkgs.lazymc
    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

  • config: attribute set, default {}
    Allows defining and overriding settings in the lazymc.toml, for all options see here. The auto generated config options are:

    • server.command: Automatically set to use the server package and jvmOpts;
    • server.directory;
    • server.address: Automatically set to 127.0.0.1:<serverProperties.server-port or 25565>";

    Firewall

    • When lazymc.enable = true, the openFirewall option for this server instance will open the port specified in lazymc.config.public.address (or its default), not the internal Minecraft serverProperties.server-port.

    Example:

    { pkgs, ... }: {
      services.minecraft-servers = {
        eula = true;
        servers.myLazyServer = {
          enable = true;
          package = pkgs.paperServers.paper-1_18_2;
          serverProperties = {
            "server-port" = 25566;
            "max-tick-time" = -1; # Recommended with lazymc
          };
    
          lazymc = {
            enable = true;
            package = let
            # you can use https://lazamar.co.uk/nix-versions/
              pkgs-with-lazymc_0_2_10 = import (builtins.fetchTarball {
                  url = "https://github.com/NixOS/nixpkgs/archive/336eda0d07dc5e2be1f923990ad9fdb6bc8e28e3.tar.gz";
                  sha256 = "sha256:0v8vnmgw7cifsp5irib1wkc0bpxzqcarlv8mdybk6dck5m7p10lr";
              }) { inherit (pkgs) system; };
            in pkgs-with-lazymc_0_2_10.lazymc;
            config = {
              public.address = "0.0.0.0:25565";
            };
          };
        };
      };
    }
    

Yeshey avatar May 20 '25 16:05 Yeshey

Maybe it would have been better to not use the server-port - 1 and just let the user do all the config themeselves, there is quite a bit of logic bc of that, but there would always be some abstraction because openFirewall would have to automatically open the port in lazymc instead of in serverproperties if it was active. And I do think that having a one click solution like this is more user friendly as long as we can make it work well

And if a user sets two mc instances in adjacent ports with lazymc, there is an assertion for that

Yeshey avatar May 20 '25 16:05 Yeshey

Please avoid closing and opening pull requests. You can force push to your branch to edit commits. Additionally, please avoid doing PRs from a master branch, as it leads to CI commits that shouldn't be in the PR (as evidenced).

You can change the branch a PR is targeting in the PR edit menu on GitHub.

Infinidoge avatar May 21 '25 20:05 Infinidoge

With regards to the actual content of the PR:

  • TOML writing can be handled through the files option of the server, as opposed to reimplementing it yourself. See here for an example
  • The lazymc config overwrites the management system config, which it should never do. Based on how you wrote it, it seems that lazymc should instead be a management system in and of itself, as right now it incorrectly overwrites load-bearing parts of the existing management systems, breaking them.
  • Overall the implementation feels... very verbose and overcomplicated.

Infinidoge avatar May 21 '25 20:05 Infinidoge

Thanks for reviewing, I didn't realize that deleting and renaming my repo would also close my PRs, I'll try to keep further changes in this one. Yeah, the code isn't ideal, when I did it i was probably thinking about my own needs more than doing something clean to try to merge, and might have used an LLM to help a bit 😅. Sorry if it wasted your time, soon as I get a bit of time I'll try to rewrite it. On a rewrite I think I'd drop the "server-port" - 1 logic, openFirewall would open the lazymc port instead of the mc server one if lazymc is enabled; and just let the user manage the ports themeselves, idk if you want to weigh in on that

Yeshey avatar May 21 '25 21:05 Yeshey

Dont use a llm for anything. opens the project up to legal issues.

Titaniumtown avatar May 25 '25 06:05 Titaniumtown

Will this eventually be merged with the main branch? This would be an awesome addition cause I'm having a tough time trying to get lazymc working with nix-minecraft manually, but having it built in would be incredible

CalmSeoul avatar Jun 21 '25 05:06 CalmSeoul

@CalmSeoul this is a clunky implementation, as it stands it should be rewriten to get merged. I will try to look at it in the summer but i cant promise. I'm not the most proficiant nixer as well. If u want to use it rn, you can import the flake from my fork and check the readme for how its set up.

Yeshey avatar Jun 21 '25 15:06 Yeshey

Rewrote the implementation, sorry for the fuss earlier, no more vibe code now, hopefully it can get merged

Yeshey avatar Aug 09 '25 04:08 Yeshey

I tested this and it works! Good job.

Only comment is that, shouldn't lazymc's public port be 25565 and the internal port be 25566? It should be transparent to the end user and not be another port imo.

Titaniumtown avatar Aug 14 '25 08:08 Titaniumtown

I thought shifting the port up or down would be kinda arbitrary and code heavy, so I decided to leave the assertion to force the user to always pick their lazymc public port instead. Maybe you're right that that should suggest port 25565, and now that I'm thinking about that, there should probably be another assertion for when the internal server port and the lazymc public port are the same

Yeshey avatar Aug 14 '25 11:08 Yeshey

Or maybe, to do it this way, the right method would be to force the user to set the serverProperties.server-port instead when lazymc is enabled

Yeshey avatar Aug 14 '25 11:08 Yeshey

There you go, I think this is better

now if a user goes

        servers.testerido = {
          enable = true;
          lazymc.enable = true;
        };

they'll get:

       error: Server 'testerido' has the same port set for serverProperties.server-port and lazymc.config.public.address
       Please set for example: `testerido.serverProperties.server-port = 25566;`, lazymc's internal server.address will automatically point to it
       Lazymc's public.address is "0.0.0.0:25565" by default

Yeshey avatar Aug 14 '25 14:08 Yeshey

Hi, are there any blockers left preventing this PR being merged? I'm interested in running lazymc with this flake.

rharish101 avatar Oct 09 '25 06:10 rharish101

Hi, are there any blockers left preventing this PR being merged? I'm interested in running lazymc with this flake.

@Titaniumtown @Infinidoge let me know if there are any more blockers, I can try to work on them to get this done! The automatic github action to update package lock files has also been failing recently, not sure why.

Yeshey avatar Oct 10 '25 08:10 Yeshey

The automatic github action to update package lock files has also been failing recently, not sure why.

That was recently fixed by #176, which got merged a few hours ago.

Also, if you need someone to test it, I can do so, once you've rebased your flake. I'm running a single Paper server. Fair warning, I've never used lazymc before 😛.

rharish101 avatar Oct 10 '25 09:10 rharish101

The automatic github action to update package lock files has also been failing recently, not sure why.

That was recently fixed by #176, which got merged a few hours ago.

Also, if you need someone to test it, I can do so, once you've rebased your flake. I'm running a single Paper server. Fair warning, I've never used lazymc before 😛.

That'd be delightful :), sorry I didn't see your response earlier! Let me see if I can rebase my flake to fix this! Lazymc is pretty straightforward, I added a section to the readme file that should help you set it up if you're willing to test it, if that's enough for you to find your way around it it would already be a testament to my assertions and bit of documentation hahaah

Yeshey avatar Oct 12 '25 10:10 Yeshey

I just tested it, and it works! My setup is just a single Paper server with lazymc enabled for it, with Velocity as a proxy. I saw a slow connection time the first time I connected to the server (after a while), but every other time, it was fast enough. I think this means that lazymc is working, right?

rharish101 avatar Oct 13 '25 20:10 rharish101

I just tested it, and it works! My setup is just a single Paper server with lazymc enabled for it, with Velocity as a proxy. I saw a slow connection time the first time I connected to the server (after a while), but every other time, it was fast enough. I think this means that lazymc is working, right?

if you have time, check if it works withmanagementSystem.systemd-socket.enable = true; as well. Last time I checked it was working properly I guess we wait for someone with write access to give us a heads up! ahah

Yeshey avatar Oct 14 '25 12:10 Yeshey

if you have time, check if it works withmanagementSystem.systemd-socket.enable = true; as well.

What's managementSystem here? I can't find a NixOS option here: https://search.nixos.org/options?channel=unstable&query=managementSystem

rharish101 avatar Oct 14 '25 14:10 rharish101

What's managementSystem here? I can't find a NixOS option here: https://search.nixos.org/options?channel=unstable&query=managementSystem

Sorry, It's a nix-minecraft option, seems like it isn't immediately found in the documentation ahaha I saw it in the code, if you put inside a nix-minecraft server config:

          managementSystem.systemd-socket.enable = true;
          managementSystem.tmux.enable = false;

it'll basically not use tmux, but there will also be no easy way to give input to the server.

Either way I did it on my own server and it seems to work as well, so at least on my side everything's working :)

Yeshey avatar Oct 14 '25 14:10 Yeshey

I tried it out, and it works on my system too.

EDIT: I just mean that the server runs with lazymc. I tested neither the systemd nor the tmux sockets.

rharish101 avatar Oct 14 '25 17:10 rharish101

Cool thanks! I rebased, but instead of renaming the branch (that would close the PR and we would loose the discussion) I disabled github actions on my fork, hopefully that prevents the clutter, I'll go through the file comments soon as I can

Yeshey avatar Oct 15 '25 11:10 Yeshey

Is there anything else left to do? I'd like to use this without manually using @Yeshey's fork.

rharish101 avatar Oct 25 '25 11:10 rharish101

Is there anything else left to do? I'd like to use this without manually using @Yeshey's fork.

I'll try to explain the situation as it is right now The way this nixOS module stops the Minecraft servers is by directly sending the letters "stop" (or any other keyword to stop the server according to the type of server) into the stdin of tmux so the server stops itself, and when the server stops, only then tmux will also exit and the systemd service will exit as well. But this is not how lazymc works, lazymc sends a SIGINT (or SIGTERM?) signal to the server and hopes that the server stops correctly independently of the type of server it is. And it doesn't expose any API so we can't easily know if the server has already shut down or not, so what enabling lazymc now does is it kills tmux (witch might bring up non fatal exception on the minecraft server because the terminal suddenly dissapears) that in turn kills lazymc witch takes care of killing the server as well with signals. This to say that lazymc handles server shutdowns fundamentally differently than this module, and accepting that would mean that all the logic for stopping servers by sending stop words is kinda irrelevant at least when lazymc is enabled. We could theoretically check if the server process is suspended or running to see if it is sleeping or not initialized and work around this, but this is complex and I think this is a pretty bad idea as lazymc is already expecting to handle server shutdown with signals.

I see why there's friction, but if @Infinidoge sees a path for this to get merged I'd also love to be able to finally get this done

Yeshey avatar Oct 26 '25 20:10 Yeshey

Sorry for the lack of responses, currently midterm season at university so I haven't been able to be active on GitHub. As such it will likely be a while longer before this will be merged.

Infinidoge avatar Oct 27 '25 05:10 Infinidoge

Sorry for the lack of responses, currently midterm season at university so I haven't been able to be active on GitHub. As such it will likely be a while longer before this will be merged.

Don't worry I know the feeling, I'm looking into this now instead of sleeping as well

Yeshey avatar Oct 27 '25 23:10 Yeshey