From 1edaae745e01d0391a98f87a2649ae8cd6594bee Mon Sep 17 00:00:00 2001 From: Callum Date: Wed, 6 May 2026 02:34:30 +1000 Subject: [PATCH 1/3] feat: add Nix flake with package, NixOS module and overlay --- .gitignore | 1 + flake.lock | 27 ++++++++++++ flake.nix | 46 ++++++++++++++++++++ nix/module.nix | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ nix/package.nix | 30 +++++++++++++ 5 files changed, 215 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/module.nix create mode 100644 nix/package.nix diff --git a/.gitignore b/.gitignore index 98a40ca6..35b772fa 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /docs/.vitepress/cache /docs/.vitepress/dist /target +/result node_modules/ *.zst .DS_Store diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..4fe7997b --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1777954456, + "narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..a254376b --- /dev/null +++ b/flake.nix @@ -0,0 +1,46 @@ +{ + description = "Lightweight Minecraft limbo server"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + outputs = + { self, nixpkgs, ... }: + let + systems = [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + ]; + forAllSystems = nixpkgs.lib.genAttrs systems; + in + { + overlays.default = final: _prev: { + picolimbo = final.callPackage ./nix/package.nix { }; + }; + + packages = forAllSystems ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}.extend self.overlays.default; + in + { + default = pkgs.picolimbo; + } + ); + + nixosModules.default = + { + pkgs, + config, + lib, + ... + }: + { + imports = [ ./nix/module.nix ]; + config = lib.mkIf config.services.picolimbo.enable { + nixpkgs.overlays = [ self.overlays.default ]; + services.picolimbo.package = lib.mkDefault pkgs.picolimbo; + }; + }; + }; +} diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 00000000..2e091c1f --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,111 @@ +{ + config, + pkgs, + lib, + ... +}: + +let + inherit (lib) + literalExpression + mkDefault + mkEnableOption + mkIf + mkOption + mkPackageOption + types + ; + cfg = config.services.picolimbo; + settingsFormat = pkgs.formats.toml { }; + configFile = settingsFormat.generate "server.toml" cfg.settings; + listenPort = lib.toInt (lib.last (lib.splitString ":" cfg.settings.bind)); +in +{ + options.services.picolimbo = { + enable = mkEnableOption "PicoLimbo, a lightweight Minecraft limbo server written in Rust"; + + package = mkPackageOption pkgs "picolimbo" { }; + + openFirewall = mkOption { + type = types.bool; + default = false; + example = true; + description = "Open the firewall port derived from {option}`services.picolimbo.settings.bind`."; + }; + + settings = mkOption { + type = settingsFormat.type; + default = { }; + description = '' + PicoLimbo configuration as a Nix attribute set, serialised to + {file}`/etc/picolimbo/server.toml` at activation time. + + Environment variable placeholders (`''${VAR}`) are expanded by the server at start-up. + + Full reference: https://picolimbo.quozul.dev/config/introduction.html + ''; + example = literalExpression '' + { + bind = "0.0.0.0:25565"; + welcome_message = "You are in limbo!"; + default_game_mode = "spectator"; + + forwarding = { + method = "MODERN"; + secret = "''${VELOCITY_SECRET}"; + }; + + server_list.message_of_the_day = "My Server"; + + tab_list = { + enabled = true; + header = "Limbo"; + footer = "Reconnecting soon…"; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + services.picolimbo.settings = { + # Provide a default bind address so the generated TOML is never empty. + # An empty file causes the server to attempt a write back to the path, + # which fails against the read-only /etc location. + bind = mkDefault "0.0.0.0:25565"; + }; + + assertions = [ + { + assertion = + (cfg.settings.forwarding or { }).method or "NONE" != "MODERN" + || (cfg.settings.forwarding or { }) ? secret; + message = "services.picolimbo.settings.forwarding.secret must be set when method is \"MODERN\""; + } + { + assertion = + (cfg.settings.forwarding or { }).method or "NONE" != "BUNGEE_GUARD" + || (cfg.settings.forwarding or { }).tokens or [ ] != [ ]; + message = "services.picolimbo.settings.forwarding.tokens must be non-empty when method is \"BUNGEE_GUARD\""; + } + ]; + + environment.etc."picolimbo/server.toml".source = configFile; + + systemd.services.picolimbo = { + description = "PicoLimbo, a lightweight Minecraft limbo server written in Rust"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + ExecStart = "${lib.getExe cfg.package} --config /etc/picolimbo/server.toml"; + StateDirectory = "picolimbo"; + WorkingDirectory = "/var/lib/picolimbo"; + DynamicUser = true; + Restart = "always"; + }; + }; + + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ listenPort ]; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 00000000..d8fb3e06 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,30 @@ +{ + lib, + rustPlatform, +}: + +rustPlatform.buildRustPackage { + pname = "picolimbo"; + version = "1.12.2+mc26.1.2"; + + src = lib.cleanSource ../.; + + cargoLock.lockFile = ../Cargo.lock; + + cargoBuildFlags = [ + "--bin" + "pico_limbo" + ]; + + meta = with lib; { + description = "A lightweight Minecraft limbo server written in Rust"; + homepage = "https://github.com/Quozul/PicoLimbo"; + license = licenses.mit; + mainProgram = "pico_limbo"; + platforms = [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + ]; + }; +} From 81d31d7c5317820f52fc91bc5e788545397187c2 Mon Sep 17 00:00:00 2001 From: Callum Date: Wed, 6 May 2026 23:27:04 +1000 Subject: [PATCH 2/3] docs: add NixOS section --- docs/about/installation.md | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/docs/about/installation.md b/docs/about/installation.md index b198cdd7..7d83ed4b 100644 --- a/docs/about/installation.md +++ b/docs/about/installation.md @@ -62,6 +62,68 @@ To use this configuration: 3. Create a `server.toml` file with your configuration 4. Run `docker compose up -d` to start the server +## Using NixOS + +The flake provides a package, nixpkgs overlay, and NixOS module. The module runs PicoLimbo as a systemd service and exposes all server settings through `services.picolimbo.settings`, which is serialised to `/etc/picolimbo/server.toml` at activation time. + +To use it: + +1. Add PicoLimbo as a flake input + +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + picolimbo.url = "github:Quozul/PicoLimbo"; + }; +} +``` + +2. Import the NixOS module + +```nix +imports = [ + inputs.picolimbo.nixosModules.default +]; +``` + +3. Enable the service + +```nix +{ + services.picolimbo = { + enable = true; + + settings = { + bind = "0.0.0.0:25565"; + max_players = 50; + welcome_message = "You were spawned in Limbo."; + }; + }; +} +``` + +It is recommended to store secrets (e.g. for forwarding) using `sops-nix` or with systemd credentials. + +```nix +{ + services.picolimbo.settings = { + bind = "0.0.0.0:25565"; + online_mode = false; + + forwarding = { + method = "MODERN"; + secret = "\${VELOCITY_SECRET}"; + }; + }; + + systemd.services.picolimbo = { + serviceConfig.LoadCredential = "velocity-secret:/path/to/velocity-secret"; + environment.VELOCITY_SECRET = "%d/velocity-secret"; + }; +} +``` + ## Binary / Standalone ### GitHub Releases From 27b91b314b202083e34e8884edade412f864c913 Mon Sep 17 00:00:00 2001 From: callum Date: Thu, 7 May 2026 13:02:47 +1000 Subject: [PATCH 3/3] fix(docs): correct invalid configuration options in NixOS section --- docs/about/installation.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/about/installation.md b/docs/about/installation.md index 7d83ed4b..b560f5e4 100644 --- a/docs/about/installation.md +++ b/docs/about/installation.md @@ -96,8 +96,11 @@ imports = [ settings = { bind = "0.0.0.0:25565"; - max_players = 50; + welcome_message = "You were spawned in Limbo."; + server_list = { + max_players = 50; + }; }; }; } @@ -109,7 +112,6 @@ It is recommended to store secrets (e.g. for forwarding) using `sops-nix` or wit { services.picolimbo.settings = { bind = "0.0.0.0:25565"; - online_mode = false; forwarding = { method = "MODERN";