Template format
A template is a YAML file. The catalogue’s games (games/ in the catalogue’s repository) are good examples; the editor writes the same format. Every field with its type and default: Template reference.
A minimal template
Section titled “A minimal template”id: echo-servername: Echo serverimages: - label: BusyBox image: busybox:1.37startupMode: shellstartup: >- echo "ready on ${SERVER_PORT}"; while read line; do echo "you said: $line"; donestop: command: stopreadyPattern: ready onports: - role: game protocol: tcp default: 40100variables: - key: MAX_PLAYERS name: Max players default: "16" rules: required|integer|between:1,64configFiles: - path: server.properties parser: properties values: - key: server-port value: "{{server.build.default.port}}" - key: max-players value: "{{env.MAX_PLAYERS}}"install: image: busybox:1.37 entrypoint: sh script: | printf 'server-port=\nmax-players=\n' > /mnt/server/server.propertiesFields
Section titled “Fields”| Field | Meaning |
|---|---|
id |
stable identifier: lowercase letters, digits, dashes |
name, description |
what users see |
images |
runtime images in order, each with a label (e.g. “Java 21”) and image; the first is the default |
architectures |
CPU architectures the images exist for, e.g. [amd64]; empty: any |
startupMode |
image (default): the image’s entrypoint reads $STARTUP, like Pterodactyl images. shell: the command runs with /bin/sh -c. |
startup |
the start command, with placeholders |
stop |
command (a console command, e.g. stop) or signal (e.g. SIGINT; default SIGTERM), and timeoutSeconds (default 30) before the server is killed |
readyPattern |
a console line containing this text marks the server as running |
ports |
ports by role, below |
variables |
settings, below |
configFiles |
values written into config files before every start: Config files and prompts |
prompts |
questions on the console, answered with a button: Config files and prompts |
install, steam |
how the game is installed and updated: Install and update jobs |
query |
how the node asks for players, below |
rcon |
a remote console, below |
ports: - role: game # the primary port; always passed as SERVER_PORT protocol: udp # tcp (default) · udp · both default: 2302 # preferred port; otherwise any free one - role: query protocol: udp default: 27016 variable: QUERY_PORT - role: ase # MTA: the server browser port is always game + 123 protocol: udp offset: 123 offsetFrom: gamevariable: the environment variable the port is passed in.offset/offsetFrom: a fixed distance from another role’s port, for games that derive it themselves. The panel then picks a pair that is free on the node.customPorts: true(top level): users add their own ports when creating a server, passed asPORT_<ROLE>. For generic templates.
Resources
Section titled “Resources”resources: memoryMb: 384 # for a small server memoryPerPlayerMb: 4 # added per player slot … playersVariable: MAX_PLAYERS # … from this variable cpuPercent: 100 # 100 = one core diskMb: 2048Recommended limits, filled in when a server is created; users can change them.
Variables
Section titled “Variables”variables: - key: RCON_PASSWORD # environment variable name: RCON password description: Turns RCON on. Empty keeps it off. default: "" visibility: secret rules: nullable|string|max:64visibility |
|
|---|---|
user (default) |
shown to and editable by the server’s users |
admin |
only tenant owners and admins see and edit it |
secret |
write-only: never shown again, stored encrypted; only owners and admins set it |
readOnly |
visible but fixed |
rules: Laravel-style validation, as in Pterodactyl eggs:required|integer|between:1,100,regex:/^[\w.-]+\.jar$/…jobOnly: true: only installs and updates get the value (download tokens, license keys); the running server never does.
Player count
Section titled “Player count”query: protocol: a2s # a2s (Steam games) · minecraft (Java Server List Ping) · mta (ASE) port: query # the port role it answers on (default: game)The node asks every 15 seconds while the server runs. Allocations bound to 0.0.0.0 are asked through the host; one bound only to 127.0.0.1 can’t be reached by an agent running in a container.
rcon: protocol: battleye # source (TCP: Minecraft, Project Zomboid, Rust…) · battleye (UDP: DayZ, Arma) port: rcon # port role (default: rcon) password: "{{env.RCON_PASSWORD}}" # usually a secret variable, also written into the game's config console: true # the console's input goes over RCONWith console: true, console commands, schedules’ commands and the stop command go over RCON, for games that read no commands from their console (DayZ).
Placeholders
Section titled “Placeholders”| Placeholder | Value |
|---|---|
{{VARIABLE}} |
a variable’s value, e.g. {{SERVER_MEMORY}} |
{{env.VARIABLE}} |
the same, in config files |
{{server.build.default.port}} |
the game port (Pterodactyl’s name) |
{{server.build.default.ip}}, {{server.build.memory}} |
the address and memory (Pterodactyl’s names) |
Every server also gets SERVER_PORT, SERVER_IP, SERVER_MEMORY (in MB; without a memory limit, 80 % of the node’s memory) and P_SERVER_UUID, as Pterodactyl images expect, plus one variable per extra port role.