Skip to main content
Reference documentation for the Nix module system and Oyasai scope used in the platform.

Oyasai scope

The Oyasai scope provides a curated set of packages and build tools.

Structure

oyasai-scope = lib.makeScope pkgs.newScope (
  scopeSelf: {
    # Build tools
    gradle = /* ... */;
    gradle2nix = /* ... */;
    jdk = /* ... */;
    jre = /* ... */;
    
    # Builders
    oyasaiPurpur = /* ... */;
    oyasaiDockerTools = /* ... */;
    
    # Plugin system
    plugins-batch = /* ... */;
    plugins = /* ... */;
    
    # Server packages
    oyasai-minecraft-main = /* ... */;
    oyasai-plugin-registry = /* ... */;
  }
);

Build tools

gradle

gradle
derivation
Gradle 9 configured with Java 25.
gradle = pkgs.gradle_9.override { java = scopeSelf.jdk; };

gradle2nix

gradle2nix
builder
Builder for Gradle projects with dependency locking.
gradle2nix.buildGradlePackage {
  pname = "plugins";
  version = "0.0.0";
  src = /* ... */;
  lockFile = ./gradle.lock;
  gradleBuildFlags = [ "build" ];
}

JDK/JRE

jdk
derivation
Temurin JDK 25 for building.
jre
derivation
Temurin JRE 25 for running servers.
jdk = pkgs.javaPackages.compiler.temurin-bin.jdk-25;
jre = pkgs.javaPackages.compiler.temurin-bin.jre-25;

Plugin system

plugins-batch

All plugins are built together in a single derivation:
plugins-batch = scopeSelf.gradle2nix.buildGradlePackage {
  pname = "plugins";
  version = "0.0.0";
  src = /* filtered source */;
  inherit (scopeSelf) gradle;
  buildJdk = scopeSelf.jdk;
  lockFile = ../gradle.lock;
  gradleBuildFlags = [ "build" ];
  
  installPhase = ''
    mkdir -p $out
    cp plugins/*/build/libs/*.jar $out
  '';
};

Individual plugins

Each plugin is derived from the batch build:
plugins = lib.mapAttrs' (
  name: _:
  lib.nameValuePair (lib.toLower name) (
    pkgs.runCommand name { } ''
      mkdir -p $out
      cp ${plugins-batch}/${name}.jar $out
    ''
  )
) (builtins.readDir ../plugins);
Access plugins:
with oyasai-plugins; [
  oyasaiutilities
  oyasaiadmintools
  vertex
]

Package creation

callPackage pattern

oyasaiPurpur = callPackage ./oyasai-purpur.nix { };
The called file receives scope arguments automatically:
# nix/oyasai-purpur.nix
{
  lib,
  stdenv,
  jre,
  purpur-version,
  ...
}:

{ name, version, plugins ? [], ... }:

# Build logic

packagesFromDirectoryRecursive

Automatically import all packages from a directory:
lib.packagesFromDirectoryRecursive {
  inherit callPackage;
  directory = ../packages;
}
This imports:
  • packages/foo.nix as foo
  • packages/bar/default.nix as bar

Flake outputs

packages

Exposed packages:
packages = lib.filterAttrs (_: availableOnSystem) {
  inherit (oyasaiScope)
    oyasai-minecraft-main
    oyasai-minecraft-marzipan
    oyasai-minecraft-minimal
    oyasai-plugin-registry
    oyasai-push-nix-images
    ;
};

legacyPackages

All plugins are available:
legacyPackages.oyasai-plugins = oyasaiScope.plugins;

checks

All derivations become build checks:
checks = lib.concatMapAttrs (
  k: v: lib.optionalAttrs (availableOnSystem v) {
    "build-${k}" = v;
  }
) (lib.filterAttrs (_: lib.isDerivation) (
  oyasaiScope // oyasaiScope.plugins
));
Run checks:
nix flake check -L

Development shells

devShells

devShells.default = pkgs.mkShell {
  buildInputs = with oyasai-scope; [
    gradle
    gradle2nix-cli
    jdk
    nodejs
    terraform
  ];
};
Enter the shell:
nix develop

Cross-platform support

System filtering

availableOnSystem = lib.meta.availableOn { inherit system; };

packages = lib.filterAttrs (_: availableOnSystem) { /* ... */ };

Platform-specific features

passthru = lib.optionalAttrs stdenv.hostPlatform.isLinux {
  docker = /* Docker image only on Linux */;
};

Overriding packages

override

myServer = oyasai-minecraft-minimal.override {
  plugins = [ /* custom plugin list */ ];
};

overrideAttrs

myServer = oyasai-minecraft-minimal.overrideAttrs (old: {
  extraJavaArgs = old.extraJavaArgs ++ [ "-Xdebug" ];
});

Best practices

Use callPackage

Automatically inject dependencies from the scope.

Filter sources

Only include necessary files in derivations.

Lock dependencies

Use gradle.lock and flake.lock for reproducibility.

Test with checks

Include all packages in flake checks.

See also

Build docs developers (and LLMs) love