Skip to main content

luminesk.toml Reference

This page documents manifest schema version 1 as accepted by the current loader. The manifest must be UTF-8, named exactly luminesk.toml, and no larger than 1 MiB. Unknown keys are rejected everywhere except vendor tables below [x].

Minimal manifest​

Place this manifest and a real server.jar.in file in the same directory. It can be statically validated, locked, packaged, and installed; replace the image and command when the artifact needs a different runtime.

manifest_version = 1

[package]
name = "local-java-core"
version = "1.0.0"
kind = "core"
game = "minecraft"
edition = "java"

[[sources]]
id = "core"
type = "local-file"
target = "server.jar"

[sources.options]
path = "server.jar.in"
version = "1.0.0"

[runtime]
image = "eclipse-temurin:21-jre"
command = ["java", "-jar", "server.jar", "nogui"]

[package] and [runtime] are always required. A recipe may omit sources, build, template, and files when the pinned runtime image contains the complete server; the resulting package contains metadata but no payload files.

Top-level fields​

FieldTypeRequiredDefaultMeaning and constraints
manifest_versionintegeryes—Must be exactly 1; this is the schema version, not the product version.
templatestringnononePortable relative path to a recipe directory copied into the package. Files ending in .tmpl are rendered and lose that suffix.
packagetableyes—Package identity and catalog metadata.
inputstable of tablesno{}Named string, integer, or boolean inputs.
sourcesarray of tablesno[]Artifacts resolved and copied or extracted into the package.
filesarray of tablesno[]Local recipe files/directories copied into the package.
ownershiptablenoempty listsRecursive preserve, data, and executable path policies.
runtimetableyes—Docker image, argv, mounts, ports, and resource policy.
buildtablenononeIsolated Dockerfile build whose selected output is packaged.
checksarray of tablesno[]Post-build, post-install, and readiness checks.
updatetablenotransactional defaultsBackup retention and rollback policy.
xtable of tablesno{}Vendor extension data. Every direct x.<vendor> value must be a table; Luminesk otherwise leaves it uninterpreted.

There is no [permissions] table and no host-command switch. A manifest that declares either is invalid. A [build] table opts into a Docker build; build.network = true explicitly gives that build Docker's default network.

Portable paths​

Recipe and instance paths must be normalized, relative, use /, and avoid ./.. segments, Windows drive/UNC forms, control characters, trailing dots or spaces, and Windows reserved names such as CON or NUL. Symlinks and special files are rejected when recipe assets, templates, build contexts, and packages are collected.

The literal . is allowed only for an extracted source target and a runtime mount source. Container locations such as build.output are documented separately.

[package]​

[package]
name = "lumi-bedrock"
version = "1.2.0"
display_name = "Lumi for Bedrock Edition"
kind = "core"
game = "minecraft"
edition = "bedrock"
summary = "A Lumi server recipe"
keywords = ["lumi", "bedrock", "plugins"]
license = "GPL-3.0-or-later"
authors = ["Example Maintainer"]
platforms = ["linux/amd64", "linux/arm64"]

[package.repository]
url = "https://github.com/example/lumi-recipe"
FieldTypeRequiredDefaultMeaning and constraints
namestringyes—Lowercase package identifier, 1–128 characters; starts/ends alphanumeric and may contain ., _, or -.
versionstringyes—Semantic version with three numeric components, optional prerelease, and optional build metadata. Mutable words such as latest are invalid here.
display_namestringnononeHuman-readable catalog/UI name.
kindstring enumyes—core or template. This is package classification, not a different schema.
gamestring enumyes—Currently only minecraft.
editionstring enumyes—java, bedrock, or cross-platform.
summarystringno""Short description; an empty string is accepted.
keywordsarray of stringsno[]Discovery terms.
licensestringnononeRecipe/package license identifier or label.
authorsarray of stringsno[]Maintainer/author labels.
platformsarray of stringsno[]Allowed host targets in os/architecture form. Empty means all supported targets. Locking fails if the current target is absent.
repositorytablenononeContains the recipe repository metadata.
repository.urlHTTPS URLyes if table exists—Absolute HTTPS URL without embedded credentials or fragment.

Supported CLI hosts are linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, and windows/amd64. Recipe targets follow the Docker Engine's platform, independently of the CLI host.

[inputs.<name>]​

[inputs.server_name]
type = "string"
default = "Minecraft Server"
prompt = "Server name"
pattern = "^.{1,80}$"

[inputs.port]
type = "integer"
default = 19132
min = 1
max = 65535

[inputs.eula]
type = "boolean"
required = true
prompt = "Accept the Minecraft EULA"

[inputs.api_token]
type = "string"
required = true
secret = true
FieldTypeRequiredDefaultMeaning and constraints
typestring enumyes—string, integer, or boolean.
defaultmatching scalarnononeMust match type. Forbidden when secret = true.
promptstringnononeHuman-facing label shown by nesk info and the interactive install/update input wizard. Automation never prompts.
minintegernononeInclusive minimum applied to integer values. Cannot exceed max; an integer default is checked immediately.
maxintegernononeInclusive maximum applied to integer values.
patternstringnononePython regular expression, compiled at manifest load and matched against the complete string value.
requiredbooleannofalsePackage building fails if neither an override nor a default supplies the input.
secretbooleannofalseRequires --set-file; cannot have a default, is not persisted, and may only be referenced by rendered files.

Use interpolation as a complete or partial string:

memory = "${input.memory}"
command = ["java", "-Xmx${input.memory}", "-jar", "server.jar"]

References use ${input.NAME} where NAME consists of letters, digits, underscore, or hyphen. Runtime, mount, port, and check interpolation is rejected for secret inputs. Template rendering converts booleans to lowercase true or false.

[[sources]]​

[[sources]]
id = "core"
type = "maven"
target = "server.jar"
max_size = 536870912
extract = false
platforms = ["linux/amd64", "linux/arm64"]
allow_http = false
allow_private_network = false

[sources.options]
repository = "https://repo.lumi.su/releases"
group = "com.koshakmine"
artifact = "Lumi"
version = "latest"
channel = "stable"
FieldTypeRequiredDefaultMeaning and constraints
idstringyes—Unique lowercase package identifier used as an update component and lock key.
typestring enumyes—http, maven, jenkins, github-release, github-source, gitlab-release, gitlab-job-artifact, mojang-version, paper, or local-file.
targetpathyes—Unique package-relative destination. . is allowed only with extract = true. Targets from multiple contributors may not collide.
optionstableyes—Provider-specific strict table; see Source Providers.
max_sizeintegerno536870912Maximum downloaded/decoded bytes (512 MiB); must be at least 1.
extractbooleannofalseSafely extract a ZIP/TAR-like artifact into target. Required for github-source.
platformsarray of stringsno[]Resolve this source only for matching os/architecture targets.
allow_httpbooleannofalsePermit plain HTTP URLs for providers with a configurable URL. HTTPS remains the safe default.
allow_private_networkbooleannofalsePermit loopback/private/link-local destinations. This expands the recipe's network trust boundary.

Every resolved source records the selected version/revision, final URL, actual size, SHA-256, media type when known, and target in the lock. local-file requires a regular file inside the recipe root and is hashed into the same content cache.

[[files]]​

[[files]]
source = "config/welcome.txt.tmpl"
target = "welcome.txt"
mode = "generated"
template = true
executable = false

[[files]]
source = "seed/world"
target = "world"
mode = "data"
FieldTypeRequiredDefaultMeaning and constraints
sourcepathyes—File or directory inside the recipe root. May be absent only when mode = "data"; that declaration creates an empty target directory.
targetpathyes—Unique package-relative destination.
modestring enumnomanagedmanaged, preserve, generated, or data.
templatebooleannofalseRender ${input.*} in each UTF-8 source file. Unlike the top-level template tree, the filename is not changed automatically.
executablebooleannofalseAdd the owner executable bit to the target file/path.

A directory source is copied recursively. Symlinks and special files are rejected. All target collisions—between build output, sources, the template tree, and declared files—are errors.

template = true renders a complete target file; it does not merge properties with an existing or server-generated configuration. Do not ship partial server-owned configs. Prefer letting the server generate the full file and protecting the path with preserve; if seeding is required, provide a complete upstream-compatible file.

[ownership]​

[ownership]
preserve = ["server.properties"]
data = ["world", "world_nether", "world_the_end", "plugins"]
executable = ["bin/start-helper"]
FieldTypeRequiredDefaultMeaning and constraints
preservearray of pathsno[]Recursively mark matching packaged paths as preserve.
dataarray of pathsno[]Recursively mark matching packaged paths as user data.
executablearray of pathsno[]Recursively add the owner executable bit.

Paths are literal prefixes, not globs. Duplicates are rejected. preserve and data paths may not overlap each other. These policies override the default ownership assigned to any matching packaged output.

[runtime]​

[runtime]
image = "eclipse-temurin:21-jre"
command = ["java", "-Xms${input.memory}", "-Xmx${input.memory}", "-jar", "server.jar", "nogui"]
workdir = "/server"
memory = "${input.memory}"
stop_signal = "SIGINT"
stop_timeout = 30
restart = "unless-stopped"
restart_limit = 0
run_as = "1000:1000"
read_only_root = true
FieldTypeRequiredDefaultMeaning and constraints
imagestringyes—OCI image tag or pinned digest. Locking resolves a tag to repository@sha256:...; installed runtime always uses the lock value.
commandnon-empty array of stringsyes—Arguments appended after the image. No shell is inserted; metacharacters remain literal argument content.
workdirstringno/serverDocker container working directory. Use an absolute container path.
memorystringnononeDocker memory limit, optionally interpolated. At start it must be a positive integer plus optional b, k, m, or g suffix.
stop_signalstringnoSIGINTPassed as Docker's container stop signal.
stop_timeoutintegerno30Seconds passed to docker stop; minimum 1.
restartstring enumnonoRuntime accepts no, on-failure, always, or unless-stopped.
restart_limitintegerno0Non-negative retry limit appended only to on-failure when nonzero.
run_asstringnononeDocker user/group expression such as 1000:1000. Ensure mounted files are accessible to it.
read_only_rootbooleannotrueAdd Docker's --read-only; writable server state must be under an rw bind mount.

If runtime.mounts is empty, Luminesk bind-mounts the instance root (.) at workdir read-write. Declaring any mounts replaces that implicit default.

[[runtime.mounts]]​

[[runtime.mounts]]
source = "."
target = "/server"
mode = "rw"
FieldTypeRequiredDefaultMeaning and constraints
sourcepathyes—Instance-relative path or .. Resolution must remain inside the instance; non-dot paths are created as directories before start.
targetstringyes—Container bind destination. Use an absolute path accepted by Docker.
modestring enumnorwrw or ro.

[[runtime.ports]]​

[[runtime.ports]]
name = "game"
host = "${input.port}"
container = 25565
protocol = "tcp"
FieldTypeRequiredDefaultMeaning and constraints
namestringyes—Human-readable mapping name.
hostinteger or input referenceyes—Host port, 1–65535 after interpolation.
containerinteger or input referenceyes—Container port, 1–65535 after interpolation.
protocolstring enumnotcptcp or udp.

String port values must be exactly ${input.name}; arbitrary numeric strings or mixed interpolation are rejected by the manifest loader. Container bindings must be unique within each protocol.

[build]​

[build]
file = ".luminesk/Dockerfile"
output = "/out"
timeout = 1200
cpu = 2
memory = "2g"
network = false
FieldTypeRequiredDefaultMeaning and constraints
filepathyes—Dockerfile inside the bounded recipe context.
outputstringyes—Absolute path copied from the finished build image into package staging.
timeoutintegerno1200Docker build timeout in seconds; minimum 1.
cpuintegerno2CPU quota in whole CPUs; minimum 1.
memorystringno2gValue passed to docker build --memory.
networkbooleannofalsefalse uses --network none; true uses Docker's default build network.

All external FROM images are resolved to repository digests and rewritten in a temporary Dockerfile. Dynamic FROM $VARIABLE is forbidden. A custom # syntax= frontend must already be SHA-256 pinned. The copied context excludes .git, .luminesk_cli, worlds, and logs, rejects links/special files, and is bounded to 20,000 files and 1 GiB.

[[checks]]​

[[checks]]
id = "ready"
phase = "readiness"
kind = "log-regex"
pattern = "Done .* For help, type"
timeout = 120
required = true
FieldTypeRequiredDefaultMeaning and constraints
idstringyes—Unique check identifier.
phasestring enumyes—post-build, post-install, or readiness.
kindstring enumyes—file, process-alive, log-regex, tcp, or command, subject to phase restrictions below.
requiredbooleannotrueA failed required check aborts its operation; optional readiness timeout continues.
pathpathfor filenonePackage/instance-relative file required by a file check.
patternstringfor log-regexnonePython regular expression searched in accumulated Docker logs.
hoststringno127.0.0.1 for TCPTCP readiness host after interpolation; only localhost or a loopback address is allowed.
portinteger or input referencefor useful tcp checksnoneTCP port, validated after interpolation.
commandnon-empty array of stringsfor command[]Argv executed by docker exec; no shell.
timeoutintegerno30Readiness polling deadline in seconds; minimum 1.

post-build and post-install currently accept only file. Readiness rejects file and supports process-alive, log-regex, tcp, and command. Checks run in declaration order. If no readiness checks exist, start uses a default five-second process-alive check.

[update]​

[update]
strategy = "transactional"
backup = ["world", "world_nether", "world_the_end", "plugins", "server.properties"]
retain_backups = 3
rollback_on_failure = true
FieldTypeRequiredDefaultMeaning and constraints
strategystring enumnotransactionalThe only supported value is transactional.
backuparray of pathsno[]Additional existing files/directories copied into each transaction backup. Missing and symlink paths are skipped.
retain_backupsintegerno3Number of newest backup directories retained after a successful transaction; minimum 0.
rollback_on_failurebooleannotrueDeclared policy value. Current transactions always attempt rollback when apply/readiness fails. Keep this true; do not treat false as a way to disable safety.

Transaction backup also includes replaced/removed package paths and prior lock, state, ownership, and recipe metadata. This is operation rollback, not a substitute for independently tested backups of production worlds.

[x.<vendor>]​

[x.example]
catalog_note = "metadata for external tooling"

The top-level x value and every direct child must be a table. Contents below that child are not validated or interpreted by Luminesk. Do not use extensions to imply runtime permissions or behavior that the public schema does not have.

Validate a manifest​

nesk validate --dir ./recipe --static
nesk validate --dir ./recipe --resolve
nesk validate --dir ./recipe --build --set eula=true
nesk lock --dir ./recipe
nesk plan --dir ./recipe --set eula=true

--resolve includes static validation and performs provider/image resolution. --build also creates a temporary package and accepts repeatable --set and --set-file inputs. A recipe with required inputs and no defaults must provide them to exercise rendering and package assembly.