Overview
Oyasai Server Platform uses Nix flakes for reproducible server configurations, plugin management, and infrastructure deployment. Every server configuration is a Nix package that can be built and run consistently across environments.
Why Nix?
Reproducibility : Identical builds on any machine
Declarative : Server configuration as code
Isolation : No dependency conflicts
Efficiency : Shared dependencies via Nix store
Version Control : Track server configurations in Git
Flake Structure
{
inputs = {
nixpkgs . url = "github:nixos/nixpkgs/nixos-25.11" ;
gradle2nix = { url = "github:oyasaiserver/gradle2nix?ref=v2" ; };
package-lock2nix = { url = "github:anteriorcore/package-lock2nix" ; };
# ...
};
outputs = { ... }: {
# Packages, devshells, checks, etc.
};
}
See flake.nix for the complete configuration.
Oyasai Scope
All Oyasai packages are organized in a custom scope defined in nix/oyasai-scope.nix.
Core Components
JDK : Temurin JDK 25
JRE : Temurin JRE 25
Gradle : Gradle 9
Node.js : v24
Terraform : Infrastructure as code
gradle2nix : Gradle to Nix converter
oyasaiPurpur : Purpur server builder function
plugins : All built plugins
plugins-batch : Batch build of all plugins
See nix/oyasai-scope.nix:79-114.
Creating Server Packages
Basic Server Configuration
Create a file in packages/ directory:
{ oyasaiPurpur , oyasai-plugin-registry }:
oyasaiPurpur rec {
name = "oyasai-minecraft-minimal" ;
version = "1.21.8" ;
directory = "local" ;
# See packages/oyasai-plugins-registry/data.json
plugins = with ( oyasai-plugin-registry . forVersion version ); [
essentialsx
fastasyncworldedit
plugmanx
];
}
Example from packages/oyasai-minecraft-minimal.nix:1-16.
Server Configuration Options
name
The package name (required):
name = "oyasai-minecraft-custom" ;
version
Minecraft version (required):
Supported versions are defined in nix/oyasai-purpur.nix:22-27.
directory
Server working directory (default: .):
directory = "local" ; # Server runs in ./local/
port
Server port (default: 25565):
plugins
List of plugin derivations:
plugins = [
plugin1
plugin2
] ;
cleanPlugins
Clean plugins directory on startup (default: true):
cleanPlugins = false ; # Keep existing plugins
passthru
Additional attributes to pass through:
passthru = {
meta = {
description = "Custom server" ;
};
} ;
Using Plugins
Access built plugins from the scope:
{ oyasaiPurpur }:
let
# Import from oyasai scope
oyasaiutilities = oyasaiScope . plugins . oyasaiutilities ;
dynamicprofile = oyasaiScope . plugins . dynamicprofile ;
in
oyasaiPurpur {
name = "my-server" ;
version = "1.21.8" ;
directory = "server" ;
plugins = [
oyasaiutilities
dynamicprofile
];
}
Available plugins (lowercase names):
oyasaiutilities
oyasaipets
oyasaiadmintools
dynamicprofile
entitypose
painttools
sociallikes3
socialvotes
tpswitch
vertex
See nix/oyasai-scope.nix:106-114 for plugin naming.
External Plugins
Use the oyasai-plugin-registry:
{ oyasaiPurpur , oyasai-plugin-registry }:
oyasaiPurpur rec {
name = "server-with-external" ;
version = "1.21.8" ;
plugins = with ( oyasai-plugin-registry . forVersion version ); [
essentialsx # EssentialsX
fastasyncworldedit # WorldEdit async
vault # Economy API
luckperms # Permissions
plugmanx # Plugin manager
];
}
Custom Plugin JARs
Include custom JAR files:
{ oyasaiPurpur , pkgs }:
let
customPlugin = pkgs . fetchurl {
url = "https://example.com/plugin.jar" ;
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" ;
};
in
oyasaiPurpur {
name = "custom-server" ;
version = "1.21.8" ;
plugins = [ customPlugin ];
}
Registering Packages
1. Create Package File
Create your server configuration in packages/:
nano packages/oyasai-minecraft-myserver.nix
2. Register in Scope
Packages in packages/ are automatically discovered via:
lib . packagesFromDirectoryRecursive {
inherit callPackage ;
directory = ../packages ;
}
See nix/oyasai-scope.nix:116-119.
3. Export as Package
Add to the exports in nix/oyasai-scope.nix:
packages = lib . filterAttrs ( _ : availableOnSystem ) {
inherit ( oyasaiScope )
oyasai-minecraft-main
oyasai-minecraft-marzipan
oyasai-minecraft-minimal
oyasai-minecraft-myserver # Add your package
;
} ;
See nix/oyasai-scope.nix:126-136.
Keep the package list sorted alphabetically (indicated by # keep-sorted start/end comments).
Building and Running
Build Package
nix build .#oyasai-minecraft-minimal
Output will be in ./result/.
Run Server
nix run .#oyasai-minecraft-minimal
The server will:
Create the configured directory
Copy plugins to plugins/
Accept EULA automatically
Start Purpur server
Run with Custom Options
nix run .#oyasai-minecraft-minimal -- --help
Pass JVM options:
nix run .#oyasai-minecraft-minimal -- -Xmx4G -Xms4G
Development Workflow
1. Create Test Configuration
Edit packages/oyasai-minecraft-minimal.nix for testing:
{ oyasaiPurpur , oyasai-plugin-registry }:
let
# Import your custom plugins from scope
inherit ( oyasaiScope . plugins ) oyasaiutilities oyasaipets ;
in
oyasaiPurpur rec {
name = "oyasai-minecraft-minimal" ;
version = "1.21.8" ;
directory = "local" ;
plugins = with ( oyasai-plugin-registry . forVersion version ); [
essentialsx
fastasyncworldedit
] ++ [
oyasaiutilities # Your custom plugin
oyasaipets # Another custom plugin
];
}
The oyasai-minecraft-minimal package is designed for local development. Feel free to modify it for your needs.
2. Build and Test
nix build .#oyasai-minecraft-minimal
nix run .#oyasai-minecraft-minimal
3. Iterate
Make changes to plugin code
Rebuild plugins: gradle build --parallel
Regenerate if needed: gradle2nix
Rebuild server: nix build .#oyasai-minecraft-minimal
Test: nix run .#oyasai-minecraft-minimal
The oyasaiPurpur Function
The oyasaiPurpur function is defined in nix/oyasai-purpur.nix.
Function Signature
{
name , # Package name (required)
version , # Minecraft version (required)
plugins , # List of plugin derivations (required)
directory ? "." , # Server directory
port ? 25565 , # Server port
passthru ? { } , # Additional attributes
cleanPlugins ? true , # Clean plugins on startup
}
See nix/oyasai-purpur.nix:11-19.
Version Support
Supported Minecraft versions:
versions = {
"1.21.8" = {
build = 2497 ;
hash = "sha256-3XsifyVVYBw5zsCR32eCdfCoH6ftaM6VTsSSS7RXXEY=" ;
};
} ;
See nix/oyasai-purpur.nix:22-27.
Server Setup
The function creates a setup script that:
Accepts the EULA
Creates plugins/ directory
Optionally cleans existing plugins
Copies plugin JARs
See nix/oyasai-purpur.nix:28-45.
Wrapper
The server is wrapped with:
Working directory setup
Plugin installation
JRE execution with server JAR
Custom port configuration
See nix/oyasai-purpur.nix:67-71.
Advanced Patterns
Multi-Environment Configs
{ oyasaiPurpur , oyasai-plugin-registry }:
let
commonPlugins = with ( oyasai-plugin-registry . forVersion "1.21.8" ); [
essentialsx
vault
];
devPlugins = with ( oyasai-plugin-registry . forVersion "1.21.8" ); [
plugmanx
fastasyncworldedit
];
in
{
production = oyasaiPurpur {
name = "oyasai-prod" ;
version = "1.21.8" ;
directory = "prod" ;
plugins = commonPlugins ;
};
development = oyasaiPurpur {
name = "oyasai-dev" ;
version = "1.21.8" ;
directory = "dev" ;
plugins = commonPlugins ++ devPlugins ;
};
}
Conditional Plugins
{ oyasaiPurpur , lib }:
let
enableDebug = true ;
debugPlugins = lib . optionals enableDebug [
plugmanx
];
in
oyasaiPurpur {
name = "conditional-server" ;
version = "1.21.8" ;
plugins = basePlugins ++ debugPlugins ;
}
Checks and CI
All packages are automatically added to checks:
checks = lib . concatMapAttrs ( k : v :
lib . optionalAttrs ( availableOnSystem v ) {
"build- ${ k } " = v ;
}
) ( lib . filterAttrs ( _ : lib . isDerivation ) ( oyasaiScope // oyasaiScope . plugins )) ;
See nix/oyasai-scope.nix:137-139.
Run all checks:
Next Steps
Plugin Development Build plugins to use in your server packages
Testing Test your server configurations locally
Gradle Workflow Manage dependencies and builds
Contributing Submit your server configurations