Luanti Game Server End-to-End Example

What this page gives you

This walkthrough explains the shipped Luanti example from manifests to running server, with focus on how cell dependencies and volumes are modeled.

Shipped example location on NetBSD:

  • /usr/share/examples/cellmgr/luanti

Topology at a glance

The Luanti example is intentionally simple:

  • one service cell: luanti-app-server
  • one persistent volume: luanti-worlddata

Current dependency model:

  • CELL_DEPENDS_ON="" (no upstream dependencies)

This is a useful contrast to multi-tier examples like MantisBT.

Manifest deep dive

luanti-app-server.cell

Key fields and why they exist:

  • CELL_CREATE_PROFILE="medium": balanced isolation profile
  • CELL_CREATE_RESERVED_PORTS="30000": reserves Luanti service port ownership
  • CELL_CREATE_RLIMIT_NOFILE="8192": file descriptor ceiling
  • CELL_CREATE_RLIMIT_AS="2147483648": virtual memory ceiling (~2 GiB)
  • CELL_CREATE_RLIMIT_CORE="0": disables core dump files
  • CELL_SUPERVISE_CMD=...luantiserver --world ... --gameid mineclonia --port 30000
  • CELL_VOLUME_MOUNTS="luanti-worlddata:/var/lib/luanti:rw"
  • CELL_HEALTHCHECK_CMD="test -f /var/lib/luanti/world/world.mt"

Modeling takeaway:

  • world state is persistent because it lives on a dedicated volume
  • runtime limits are explicit in the manifest, not hidden in ad-hoc scripts

luanti-worlddata.volume

The volume manifest defines a named persistent storage object for game data.

Because the server cell mounts it rw, world changes survive cell restarts, reconciliations, and host reboots.

luanti-app-server.apply

Plan behavior:

  • installs required packages (unzip, luanti)
  • prepares game and world directories under /var/lib/luanti
  • downloads and installs the Mineclonia game only if missing
  • writes world.mt
  • writes minetest.conf with baseline server settings

The long EXEC line is intentionally idempotent: it only fetches/extracts the game when game.conf is missing.

End-to-end deployment steps

Run commands as root (or prefix with doas).

  1. bootstrap host once (skip if already done)
cellmgr system bootstrap
  1. copy shipped example manifests
cp /usr/share/examples/cellmgr/luanti/* /etc/cellmgr/
  1. inspect desired manifests
cellmgr cell show luanti-app-server --view desired
cellmgr volume list --view desired
  1. run dry-run
cellmgr apply --dry-run luanti-app-server
  1. apply changes
cellmgr apply luanti-app-server
  1. verify runtime health
cellmgr cell list --view merged
cellmgr volume list --view merged
cellctl list -T
cellctl stats -T
  1. verify world files in-cell
cellmgr cell shell luanti-app-server
# inside cell shell
ls -la /var/lib/luanti/world
cat /var/lib/luanti/world/world.mt
exit
  1. connect from a Luanti client
  • server address: <host-ip>
  • port: 30000

How to extend dependency modeling

This example has no deps by default. If you later split services, add explicit dependencies in CELL_DEPENDS_ON.

Example direction:

  • add a separate voice/chat side service cell
  • keep game world in luanti-worlddata
  • set edge/service dependency ordering explicitly

Then run the usual safe sequence:

cellmgr apply --dry-run --all
cellmgr apply --all

Operations notes after go-live

  • back up world state: cellmgr volume backup create luanti-worlddata
  • review rlimits after load testing (players, mods, map growth)
  • keep manifest changes in version control