Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/docs/.vitepress/cache
/docs/.vitepress/dist
/target
/result
node_modules/
*.zst
.DS_Store
64 changes: 64 additions & 0 deletions docs/about/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,70 @@ 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";

welcome_message = "<red>You were spawned in Limbo.</red>";
server_list = {
max_players = 50;
};
};
};
}
```

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";

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
Expand Down
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -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;
};
};
};
}
111 changes: 111 additions & 0 deletions nix/module.nix
Original file line number Diff line number Diff line change
@@ -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 = "<green>You are in limbo!</green>";
default_game_mode = "spectator";

forwarding = {
method = "MODERN";
secret = "''${VELOCITY_SECRET}";
};

server_list.message_of_the_day = "<gold>My Server</gold>";

tab_list = {
enabled = true;
header = "<bold>Limbo</bold>";
footer = "<green>Reconnecting soon…</green>";
};
}
'';
};
};

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 ];
};
}
30 changes: 30 additions & 0 deletions nix/package.nix
Original file line number Diff line number Diff line change
@@ -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"
];
};
}