Server Configuration

Configure a hosted server, including the global server config and per-session server profiles.

This guide covers how to configure a hosted server, including the global server config file and per-session server profiles, and how to run a dedicated (headless) server.


Running a Dedicated Server

creation_server is the headless server: the same server the game runs when you host from the menu, without the game attached. It has no window and needs no GPU, so it runs on a plain Linux or Windows machine.

Run it from a folder laid out like the game’s — it reads saves/, instances/, server_config/, server_profiles/ and certs/ from the working directory and writes to logs/:

creation_server --save <name> [--port <n>] [--profile <name>] [--upnp]
                [--create [--seed <seed>] [--difficulty <tier>] [--terrain <style>]]
OptionMeaning
--save <name>The save under saves/ to host. Required.
--port <n>TCP port to listen on. Defaults to 42069, the port the in-game host menu uses.
--profile <name>The server profile under server_profiles/ to apply (see Server Profiles).
--upnpOpen the port on your router with UPnP and listen on the machine’s LAN address. Without it the server listens on every interface and port forwarding is up to you.
--createCreate the save before hosting it. Refused if a save with that name already exists, so an existing save is never changed.
--seed <seed>With --create: the world seed. Random if omitted.
--difficulty <tier>With --create: dormant, awakened, forsaken or condemned. Defaults to awakened.
--terrain <style>With --create: slopes or blocky. Defaults to slopes. Fixed for the life of the save.

Players join with the machine’s address and port from the Join via IP menu. Steam P2P hosting and the host’s automatic operator status are game-only: on a dedicated server, operators come from server_config.yaml and the profile.

Stop it with Ctrl-C. The server finishes saving every world before it exits, the same as closing a hosted game.

The Steam library

The server links the Steam API (it validates session tickets under auth-mode: steam), so the Steam library has to sit next to the binary:

PlatformFile
Windowssteam_api64.dll beside creation_server.exe
Linuxlibsteam_api.so beside creation_server

Both ship in the server download. If you build from source instead, copy the library out of the build output (target/<profile>/steam_api64.dll on Windows; on Linux it is written to target/<profile>/build/steamworks-sys-*/out/libsteam_api.so). The Linux binary carries an $ORIGIN runpath, so a copy beside it is found with no LD_LIBRARY_PATH to set.

On the first launch of a save the server writes a self-signed certificate to certs/server/, and logs a couple of “Failed to read server data file” / “Error loading biome IDs” errors while it generates the world for the first time. Both are expected on a brand-new save.


Global Server Config

File: server_config/server_config.yaml

This file sets the default behaviour for every server session. Any value here can be overridden on a per-profile basis (see Server Profiles below).

Three of these values are also editable in-game, on the Configure Host screen when you host from the game rather than running a dedicated server: the authentication mode, friendly fire and the operators list. See Host Session Settings for how those interact with this file. Everything else — rate limits, connection caps, mob limits, chat settings — is file-only, because it is a dedicated-server concern.


Authentication Mode

auth-mode: steam

Controls how the server verifies player identity at login.

ValueBehaviour
steamPlayers must be logged into Steam. The server verifies their identity using a Steam session ticket. Player saves are tied to the player’s Steam account.
offlineNo verification — the server trusts whatever name the client provides. Suitable for private LAN sessions or local testing only.

Note: In steam mode, operator permissions (see below) must use the player’s Steam ID, not their display name. Steam IDs appear in the server log when a player connects.


Operators

operators:
  - 76561198000000000
  - 76561198000000001

A list of player IDs that have operator-level permission. Operators can use privileged chat commands such as /kick, /ban, /mute, and /teleport.

  • In steam mode: use the player’s Steam ID (a 17-digit number shown in the server log on login).
  • In offline mode: use the player’s login ID (the save ID sent at login, shown in the server log) — not the display name, which can be changed freely and is never used for permission checks.

Operator lists from profiles are added to this list — they never replace it. A player in either list has operator access.

Security: operator commands from the operators: list are disabled by default under offline auth, because offline mode does not verify identity — any connecting player could claim a configured operator’s login ID and gain operator powers. (The host’s own automatic grant is separate — see Automatic Operators.) On a public server, use steam auth so operator identity is verified. See Offline Operators below to re-enable them on a trusted private server.


Automatic Operators

You do not have to list yourself here to be an operator on a server you run:

  • The player who hosts the server is automatically granted operator for that session. This is resolved from your own identity when you start hosting and is not stored in the save or the profile — so it applies whichever profile you host under, and hosting a world you downloaded from someone else grants operator to nobody but you. It works under both auth modes: allow-offline-operators gates the configured operators: list, not your own grant, because hosting is not a claimed identity — it is the process you are running. (Nobody else can claim your login ID while you are connected: the server refuses a second live session on an ID that is already online.)
  • In singleplayer, the local player is always an operator; no configuration is needed.

To grant operator to other people persistently (co-admins), add them to the operators: list here or in a profile, as described above.


Offline Operators

allow-offline-operators: false
ValueBehaviour
false (default)Under offline auth, the configured operators: list is refused, because player identity cannot be verified. The host’s own automatic grant (above) is unaffected. Has no effect under steam auth, where operators always work.
trueHonor the operators: list under offline auth. Only enable this on a trusted LAN/private server where you control who can connect, since a malicious client can impersonate any operator’s login ID.

When operators are configured but disabled by this default, the server logs a warning at startup explaining how to enable them or switch to Steam auth.


Chat

chat:
  log-messages: true
  slowdown-ms: 500
  announce-player-connections: true
  history-size: 20
  max-message-chars: 256
FieldDefaultDescription
log-messagestrueWrite chat messages to the server log file.
slowdown-ms500Minimum time in milliseconds a player must wait between chat messages. Defaults to 500 (about two messages/second) to curb flooding; set 0 to disable the limit.
announce-player-connectionstrueBroadcast a message to all players when someone joins or leaves.
history-size20Number of recent messages sent to a player when they join mid-session. 0 disables replay.
max-message-chars256Maximum character length of a single chat message. Maximum allowed value is 4096.

Friendly Fire

pvp:
  friendly-fire: false
FieldDefaultDescription
friendly-firefalseWhether players can damage each other, and each other’s tamed creatures.

Every player in a world counts as an ally of every other one — there is no party to join and nothing to invite anyone to, the world is the team — and a tamed creature is an ally of its owner. With friendly-fire: false, no player-sourced damage reaches an ally: melee swings, arrows and other projectiles, thrown flasks and every other AoE zone, granted combat verbs, and damage dealt from a mod’s Lua script are all covered by the same rule.

Ambient hazards are unaffected either way. Lava, rot gas, an ash storm and any other hazard that belongs to the world rather than to a player still hurt everyone standing in it.

Operators can flip the setting for the rest of the session with /pvp <on|off>, which overrides the value here until the server restarts.


Rest

rest:
  hostile-radius: 20
FieldDefaultDescription
hostile-radius20How close (in blocks) a contact-damaging monster may be before resting to dawn at a bed is refused. Set to 0 to disable the check.

Resting to dawn at a bed is refused while any monster that deals contact damage is within hostile-radius blocks of the resting player, so a base under attack can’t skip the night. In multiplayer the world only advances once every present player has bedded down. Setting the radius to 0 removes the proximity check entirely — a bed then always rests, regardless of nearby monsters.


Rate Limiting

rate-limiting:
  packets-per-second: 300
  burst-size: 100
  chunk-packets-per-second: 1000
  chunk-burst-size: 1024
  violation-limit: 1000
  violation-decay-per-second: 20

Controls how aggressively the server throttles clients that send packets too quickly. These defaults are suitable for normal play and generally do not need to be changed.

A playing client sends about 120 packets per second by itself — movement and primary-use are each capped at 60/s on the client — so lowering packets-per-second near that figure will drop real inputs during a fight. Violations also decay: violation-decay-per-second is forgiven every second, so violation-limit measures a sustained flood rather than a running session total.

Chunk requests get their own, looser token bucket (chunk-*) because a client legitimately requests one chunk per position in its render distance all at once while a world loads — a burst the general limit would reject. The server also validates that each requested chunk is near the player’s actual position, so a looser chunk bucket does not expose the server to far-away chunk-flooding.

FieldDefaultDescription
packets-per-second300Sustained packet rate a client is allowed to send.
burst-size100How many extra packets a client can send in a short burst before throttling begins.
chunk-packets-per-second1000Sustained chunk-request (code 300) rate a client is allowed to send, on a separate bucket from the general limit.
chunk-burst-size1024How many chunk requests a client can send in a short burst — sized to cover a full render-distance initial load.
violation-limit1000Number of throttled (excess) packets allowed before the client is disconnected.
violation-decay-per-second20Violations forgiven per second, so the limit above measures a sustained flood rather than a session total. 0 restores a cumulative count.

Connection Limits

connection-limits:
  max-connections: 256
  max-connections-per-ip: 8
  handshake-timeout-seconds: 30
  idle-timeout-seconds: 120

Bounds how many clients may connect and how long a silent connection is tolerated, so a flood of connections or stalled peers can’t exhaust server resources. These defaults suit normal play and rarely need changing. Unlike the chat and rate-limiting blocks, connection-limits is a global-only setting — it is not a profile override.

FieldDefaultDescription
max-connections256Maximum concurrent client connections. Peers beyond this are dropped immediately after the TCP accept, before the TLS handshake. Set to 0 to disable the cap.
max-connections-per-ip8Maximum concurrent connections from a single source, so one client can’t fill every slot. On a direct (TCP/TLS) server that source is the peer’s IP address; on a Steam P2P server it is the connecting Steam account. Set to 0 to disable.
handshake-timeout-seconds30Seconds a freshly connected client may stay silent before sending its login request (code 600) before being disconnected.
idle-timeout-seconds120Seconds an in-game client may stay silent before being disconnected. In-game clients send movement packets ~60×/second, so this only reaps dead/stalled connections.

Mob Limits

mob-limits:
  - spawn-group: Neutral
    limit: 50
  - spawn-group: Hostile
    limit: 50

Sets a cap on how many mobs of each group can exist in the world at once, and doubles as the allow-list for natural spawning: a mob whose spawn-group has no entry here is never chosen by the natural spawner, so it will not spawn on its own (it can still be summoned or spawned by scripts/structures). The spawn-group value is matched against a mob’s own spawn-group case-insensitively — Hostile, hostile, and HOSTILE are the same group. Neutral and Npc always exist as groups even with no entry here, but still need an entry to spawn naturally. You can add as many entries as needed — one per spawn group.

The shipped roster uses three naturally-spawning groups — Neutral, Hostile, and Elite. The example ships Neutral and Hostile; Elite is intentionally held out until an elite mob is authored, because the spawner picks a group uniformly and an empty group wastes the spawn attempt. Boss and Npc are deliberately left out: a group with no entry is never drawn by the spawner, which is what a placed boss set-piece and a one-time authored NPC want (leaving them in would make the world randomly spawn bosses and named NPCs). When a mob declares a spawn-group (and spawn-rules) with no matching mob-limits entry, the server logs a warning at load naming the group, since it will otherwise silently never spawn.

An entry takes exactly spawn-group and limit; any other key fails that entry at load with a named error. A bad entry skips only itself, so the rest of your limits still apply — but a skipped entry means that group never spawns naturally, so read the log if a mob stops appearing.

Renamed in this version. This key was type: in earlier versions. An un-migrated server_config.yaml logs an error naming the old key and skips that entry (which silently disables natural spawning for that group), so rename it when you upgrade.


Required Client Mods

required-client-mods:
  - SomeTexturePack
  - AnotherClientMod

A list of client-only mod names (e.g. a texture pack marked side: client) that a connecting client must have installed, even though the server itself never loads them. They are advertised to the client during the connection handshake and reuse the same mod-compatibility warning dialog as the instance check. Defaults to empty (no extra client mods required).


Server Profiles

Server profiles let you save different server configurations and switch between them when hosting a session. This is useful if you host the same world for different audiences — for example, a private session for friends and a public session — without editing the global config each time.

Each profile is a folder inside server_profiles/:

server_profiles/
  my_profile/
    config.yaml   ← settings that override server_config.yaml

Profiles are created automatically when you select a new profile name in the host menu.

Where that folder is depends on which one is reading it. creation_server uses the server_profiles/ beside itself, so an operator’s profiles sit with the server they unpacked. The game reads the profiles that shipped with it and writes the ones you create or edit to your own settings folder (%APPDATA%\Creation on Windows, ~/Library/Application Support/Creation on macOS, ~/.local/share/creation on Linux), so a game update or a Verify integrity of game files leaves them alone. Both sets are offered in the host menu as one list.


Profile Config (config.yaml)

A profile’s config.yaml overrides specific values from server_config/server_config.yaml. Any field you omit is inherited from the global config — you only need to specify what you want to change.

All available overrides:

# Override authentication mode for this profile.
# "steam" or "offline". Inherits global value if omitted.
auth-mode: steam

# Additional operators for this profile. These are added to (not replacing)
# the global operators list in server_config.yaml.
operators:
  - 76561198000000000

chat:
  log-messages: true
  slowdown-ms: 500
  announce-player-connections: true
  history-size: 20
  max-message-chars: 256

rate-limiting:
  packets-per-second: 300
  burst-size: 100
  chunk-packets-per-second: 1000
  chunk-burst-size: 1024
  violation-limit: 1000
  violation-decay-per-second: 20

All fields are optional. A completely empty config.yaml is valid — it simply inherits everything from the global config.


Host Session Settings

When you host from inside the game, the Configure Host screen offers the small subset of this configuration a host playing with friends actually changes: authentication mode (who may join), friendly fire, and the operators list (comma-separated player IDs — the login/save names, not display names). Everything else stays in the files.

The screen opens showing what the session would run with today — the global config with the selected profile’s overrides applied — so hosting without touching it changes nothing. Selecting a different profile in the dropdown re-reads that profile’s values into the three fields.

These settings apply to the session only. No profile is ever rewritten.

LayerSourceNotes
1 (lowest)server_config/server_config.yamlThe defaults for every session
2The selected profile’s config.yamlOverrides the global value where present
3 (highest)The Configure Host screenThe session only — nothing is written back

Your last choices are remembered in game_config/host_preferences.yaml in that same settings folder, under a session: block, together with the profile they were made against. (That same file also records last-world and last-world-hosted — the world the main menu’s Continue button offers, and whether it resumes solo or brings you back to this screen.) They are reapplied only when you host under that same profile again; pick a different one and its own values are read instead. To change a profile permanently, edit its config.yaml.

Two details worth knowing:

  • The operators field is the whole effective list for the session, not an addition to it. It opens pre-filled with the global list plus the selected profile’s (which is how the two combine on the server), so a name you delete there really is not an operator for that session. The automatic host grant is separate and always applies.
  • A dedicated server (creation_server) passes none of this. It is configured entirely from server_config.yaml and its profile, which is the audience those files are kept for.

Moderation State (saves/<world>/moderation.yaml)

Mutes and bans belong to the world, not to the profile it is hosted under, so they live in the save folder rather than in server_profiles/. Banning a player from one world does not ban them from another world you host, and a world keeps its ban list whichever profile you next host it with.

The file is managed automatically by the server — /mute, /unmute, /ban and /unban rewrite it. You should not edit it by hand unless you need to remove a ban or clear the mute list while the server is offline.

muted-players:
  - 76561198000000000

banned-players:
  76561198000000001: 'Reason for ban'

Both keys are optional, and a ban may be written with no reason (76561198000000001:), in which case the player sees the default rejection message.


Session Lock (saves/<world>/session.lock)

While a server has a save open it writes a heartbeat to session.lock in that save’s folder, every five seconds, and deletes the file when it shuts down cleanly. The game’s save list reads it and refuses to delete a save that is currently being hosted, so a deletion cannot race a running server’s next autosave.

You do not need to manage this file. If a server is killed or crashes it leaves the lock behind, and a heartbeat more than 30 seconds old is ignored — the save becomes deletable again on its own. The lock is a courtesy between the game’s own processes, not a permission check: it does not stop you moving, copying or deleting the folder yourself.

heartbeat-unix-seconds: 1789123456
pid: 4821

Example: Public vs. Private Profiles

server_profiles/public/config.yaml

auth-mode: steam

chat:
  slowdown-ms: 2000
  max-message-chars: 128

server_profiles/private/config.yaml

auth-mode: offline

chat:
  announce-player-connections: false

Both profiles share the global operator list. The public profile adds chat rate limiting and Steam auth. The private profile uses offline mode and skips join/leave announcements. Note that allow-offline-operators is a global server_config.yaml setting, not a profile override — set it there (see above), not in a profile’s config.yaml, where it would be ignored.


Operator Commands Reference

Operators can run the following commands in chat:

CommandDescription
/kick <player>Disconnect a player from the server.
/ban <player> [reason]Permanently ban a player from the world being hosted.
/unban <player>Remove a ban from the world being hosted.
/mute <player>Prevent a player from sending chat messages.
/unmute <player>Restore a player’s chat access.
/pvp <on|off>Toggle friendly fire for the session — whether players can damage each other and each other’s tamed creatures, across every damage source. Overrides pvp: friendly-fire: until the server restarts.
/op <player>Grant operator to a connected player, stored in that world’s moderation.yaml alongside its mutes and bans. Survives a restart; scoped to the world, so it does not follow the player into other worlds you host. Never rewrites this file or a profile. Refused under offline auth unless allow-offline-operators is set — the same identity problem that gates the operators: list below, which applies to a stored grant equally.
/deop <player>Remove an /op grant from that world. Operators from the operators: list below, and the host’s own automatic grant, are configuration and are not removable this way.
/teleport <player> (alias /tp)Teleport to another player.
/noclipToggle noclip movement for yourself.
/capability (alias /cap)Show a player’s capabilities and where each one comes from. /capability grant <name> [player] and /capability revoke <name> [player] add or remove a persistent grant — useful for testing capability-gated content such as the double_jump and air_dash movement verbs without first authoring the gear that grants them.
/rollcatch [count]Roll the fishing catch table for the water you are standing in and report a tally of what came up, without granting anything. Content tool for tuning catch tables — see Fish Configuration.
/listShow all currently connected players.
/seedShow this world’s numeric seed (read-only). It reproduces a world only at the same game version and mod set; a new seed is a new world.
/helpShow available commands.

Operator status is granted through the operators: list and the automatic host grant described above — there is no in-chat /op or /deop command. /list, /seed and /help are available to everyone, not just operators.

Player arguments can be the player’s display name or their player ID. In steam auth mode, the player’s display name is their Steam persona name.

A <player> argument is matched against player IDs first (the verified, unique key), then against display names. Display names are unique per server — a login is refused if its display name is already in use (compared case-insensitively) — so a name resolves to at most one player. Matching the verified key first means a player cannot receive a command aimed at someone’s player ID by taking that ID as their display name. If an argument still matches more than one online player, the command fails and lists the candidates instead of guessing; target them by their exact player ID. /mute, /unmute, /ban and /unban also accept a bare player ID so offline players can be targeted.

Last updated