<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://developer.vellocetsoftware.com/index.php?action=history&amp;feed=atom&amp;title=Grimwar%2FDedicated_servers</id>
	<title>Grimwar/Dedicated servers - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://developer.vellocetsoftware.com/index.php?action=history&amp;feed=atom&amp;title=Grimwar%2FDedicated_servers"/>
	<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Dedicated_servers&amp;action=history"/>
	<updated>2026-10-21T20:42:33Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Dedicated_servers&amp;diff=140&amp;oldid=prev</id>
		<title>DocumentationBot: Version 1</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Dedicated_servers&amp;diff=140&amp;oldid=prev"/>
		<updated>2026-10-01T04:13:05Z</updated>

		<summary type="html">&lt;p&gt;Version 1&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{GameNav}}&lt;br /&gt;
Community dedicated servers keep configuration, add-ons, state, cache, replays, and secrets in an isolated writable data directory. The game installation remains read-only and can be replaced during an update.&lt;br /&gt;
&lt;br /&gt;
Community operators configure this environment. Vellocet manages official servers separately.&lt;br /&gt;
&lt;br /&gt;
== Create the server data directory ==&lt;br /&gt;
&lt;br /&gt;
Assign a different absolute data directory to each server process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
GrimwarServer --data-dir /srv/grimwar/community-1 --server-preflight-only&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Preflight checks the runtime, creates missing operator files, and exits. A normal first launch creates the same layout. Existing operator files are not overwritten.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;--instance-id &amp;amp;lt;id&amp;amp;gt;&amp;lt;/code&amp;gt; when the default per-user server location is suitable. &amp;lt;code&amp;gt;GRIMWAR_DATA_DIR&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GRIMWAR_INSTANCE_ID&amp;lt;/code&amp;gt; provide the corresponding environment settings. Never point two running processes at the same data directory.&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;code&amp;gt;cmdlhelp&amp;lt;/code&amp;gt; in the server console for the current command-line contract. Run &amp;lt;code&amp;gt;cfg_paths&amp;lt;/code&amp;gt; for the resolved install, data, config, secret, add-on, replay, state, and cache paths.&lt;br /&gt;
&lt;br /&gt;
=== Common launch options ===&lt;br /&gt;
&lt;br /&gt;
The shared name, map, player-limit, and password contract is documented in [[Dedicated server launch settings]]. Use the traditional aliases on older Grimwar releases. The options below cover Grimwar-specific setup and those existing aliases.&lt;br /&gt;
&lt;br /&gt;
Switches accept &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;--&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt;. A value may follow the switch or use &amp;lt;code&amp;gt;=&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Option !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--data-dir &amp;amp;lt;path&amp;amp;gt;&amp;lt;/code&amp;gt; || Select an absolute writable data root.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--instance-id &amp;amp;lt;id&amp;amp;gt;&amp;lt;/code&amp;gt; || Select a named data root below the default per-user location.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--map &amp;amp;lt;map-id&amp;amp;gt;&amp;lt;/code&amp;gt; || Start on a registered map. This does not replace the saved rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--mode &amp;amp;lt;mode-id&amp;amp;gt;&amp;lt;/code&amp;gt; || Override the startup mode, or select the first rotation entry using that mode when no map is supplied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--hostname &amp;amp;lt;name&amp;amp;gt;&amp;lt;/code&amp;gt; || Override the browser name for this process.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--max-players &amp;amp;lt;count&amp;amp;gt;&amp;lt;/code&amp;gt; || Override the total playable slots.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--steam-game-port &amp;amp;lt;port&amp;amp;gt;&amp;lt;/code&amp;gt; || Change the internal Steam game-service UDP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--steam-query-port &amp;amp;lt;port&amp;amp;gt;&amp;lt;/code&amp;gt; || Change the internal Steam query UDP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--server-preflight-only&amp;lt;/code&amp;gt; || Validate configuration and create missing operator files, then exit before platform login.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--server-startup-smoke&amp;lt;/code&amp;gt; || Initialize content, Workshop, security, and platform services, then exit before publication.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;+&amp;amp;lt;console-variable&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt; || Apply a non-secret console-variable override after &amp;lt;code&amp;gt;autoexec.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Prefer the secret files described below for passwords. Join-password launch options are supported, but users with sufficient machine access can inspect command lines. Keep platform credentials in the secret environment or deployment files.&lt;br /&gt;
&lt;br /&gt;
== Network transport and ports ==&lt;br /&gt;
&lt;br /&gt;
Community servers use Steam Relay for gameplay and Steam public discovery. The stock server does not accept direct-IP gameplay joins, so do not expose or forward a gameplay UDP port. Install the current dedicated-server build through SteamCMD and allow outbound Steam and HTTPS traffic.&lt;br /&gt;
&lt;br /&gt;
The internal Steam service defaults are &amp;lt;code&amp;gt;27015/UDP&amp;lt;/code&amp;gt; for the game service and &amp;lt;code&amp;gt;27016/UDP&amp;lt;/code&amp;gt; for queries. Change them only when another local process owns one of those ports. Keep the values distinct.&lt;br /&gt;
&lt;br /&gt;
RCON is separate. Its default &amp;lt;code&amp;gt;27015/TCP&amp;lt;/code&amp;gt; does not conflict with &amp;lt;code&amp;gt;27015/UDP&amp;lt;/code&amp;gt;. Expose the RCON TCP port only to administrator addresses or a private network.&lt;br /&gt;
&lt;br /&gt;
Official servers use managed direct UDP. A matchmaking deployment is visible only to its assigned players. A standalone official deployment appears in the browser with an &amp;#039;&amp;#039;&amp;#039;Official&amp;#039;&amp;#039;&amp;#039; badge, but its endpoint is withheld until the joining Steam identity is verified. Community builds cannot enable this contract with a name, tag, or config value.&lt;br /&gt;
&lt;br /&gt;
=== Public discovery and stable references ===&lt;br /&gt;
&lt;br /&gt;
The in-game browser reads community servers directly from Steam. It accepts only the current Grimwar app, secure dedicated-server listings, complete compatible metadata, and a Steam FakeIP. The FakeIP is a relay address rather than the host&amp;#039;s origin address. The client does not make separate ping, rules, player, or A2S queries and always joins by the server&amp;#039;s numeric SteamID through Steam Relay.&lt;br /&gt;
&lt;br /&gt;
The server is discoverable after it logs &amp;lt;code&amp;gt;Steam relay identity allocated for community discovery&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Steam GameServer online&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;advertise=True&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Dedicated server ready; publication is open&amp;lt;/code&amp;gt;. No Supabase account, directory registration, public gameplay port, or IP disclosure is required. A compatible current client only needs to refresh the Internet tab.&lt;br /&gt;
&lt;br /&gt;
A game-server login token is optional for discovery. Without one, Steam assigns an anonymous server account whose SteamID may change after a restart. For a durable console reference, create a Grimwar game-server login token and set it as the secret environment variable &amp;lt;code&amp;gt;SERVER_PLATFORM_CREDENTIAL&amp;lt;/code&amp;gt; in the hosting panel. Steam then logs the process into a persistent game-server account. Never pass the token through &amp;lt;code&amp;gt;-gslt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;--gslt&amp;lt;/code&amp;gt;, a panel note, or another command-line value; those switches are unsupported and command lines and logs may expose their contents. Rotate a token immediately if it is disclosed.&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;code&amp;gt;server_id&amp;lt;/code&amp;gt; in the server console to print the connection SteamID. Players can keep this relay-safe reference in their notes and reconnect from the game console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
connect 90292054295284751&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use the value printed by that server, not the example above. Steam&amp;#039;s desktop Favorites feature stores an address and ports; it is separate from a Grimwar SteamID note and should not be treated as the server&amp;#039;s durable identity.&lt;br /&gt;
&lt;br /&gt;
== Operator files ==&lt;br /&gt;
&lt;br /&gt;
The first normal or preflight launch creates the following files and directories below the data root:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Path !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/server.cfg&amp;lt;/code&amp;gt; || Base non-secret settings.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/server.d/&amp;lt;/code&amp;gt; || Split non-secret &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; files.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/rulesets/&amp;lt;/code&amp;gt; || Operator-defined rulesets.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/modes/&amp;lt;/code&amp;gt; || Per-mode overrides named &amp;lt;code&amp;gt;&amp;amp;lt;mode-id&amp;amp;gt;.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/maps/&amp;lt;/code&amp;gt; || Per-map overrides named &amp;lt;code&amp;gt;&amp;amp;lt;map-id&amp;amp;gt;.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/autoexec.cfg&amp;lt;/code&amp;gt; || Final non-secret overrides.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/motd.html&amp;lt;/code&amp;gt; || Optional message-of-the-day HTML fragment.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/bots.cfg&amp;lt;/code&amp;gt; || Optional bot display names, one per line.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/banned_user.cfg&amp;lt;/code&amp;gt; || Persistent SteamID bans.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/rotation.json&amp;lt;/code&amp;gt; || Ordered map/mode rotation or map blacklist.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/server-addons.json&amp;lt;/code&amp;gt; || Workshop items, manual bindings, and collections.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/mods/&amp;lt;/code&amp;gt; || VMod Admin users, groups, capability grants, and other mod configuration.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;secrets/server.secrets.cfg&amp;lt;/code&amp;gt; || Sensitive settings such as the RCON password.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;secrets/server.secrets.d/&amp;lt;/code&amp;gt; || Split sensitive &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; files.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;secrets/deployment.cfg&amp;lt;/code&amp;gt; is not an operator file. A hosting environment may generate it as the final, owner-restricted override layer.&lt;br /&gt;
&lt;br /&gt;
== Config precedence ==&lt;br /&gt;
&lt;br /&gt;
The server applies configuration in this order. A later assignment to the same console variable wins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Order !! Source&lt;br /&gt;
|-&lt;br /&gt;
| 1 || &amp;lt;code&amp;gt;config/server.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 2 || &amp;lt;code&amp;gt;config/server.d/*.cfg&amp;lt;/code&amp;gt;, sorted by filename without regard to case&lt;br /&gt;
|-&lt;br /&gt;
| 3 || The ruleset selected by &amp;lt;code&amp;gt;sv_ruleset&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4 || &amp;lt;code&amp;gt;config/modes/&amp;amp;lt;active-mode-id&amp;amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 5 || &amp;lt;code&amp;gt;config/maps/&amp;amp;lt;active-map-id&amp;amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 6 || &amp;lt;code&amp;gt;config/autoexec.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Command-line &amp;lt;code&amp;gt;+variable value&amp;lt;/code&amp;gt; overrides&lt;br /&gt;
|-&lt;br /&gt;
| 8 || &amp;lt;code&amp;gt;secrets/server.secrets.d/*.cfg&amp;lt;/code&amp;gt;, sorted by filename without regard to case&lt;br /&gt;
|-&lt;br /&gt;
| 9 || &amp;lt;code&amp;gt;secrets/server.secrets.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Generated &amp;lt;code&amp;gt;secrets/deployment.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each non-comment line in a normal CFG file is submitted as a console command. Quote values that contain spaces:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
hostname &amp;quot;Toronto Community Server&amp;quot;&lt;br /&gt;
bot_quota 4&lt;br /&gt;
mp_timelimit 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use numeric prefixes when the order inside &amp;lt;code&amp;gt;server.d&amp;lt;/code&amp;gt; matters, such as &amp;lt;code&amp;gt;10-identity.cfg&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;20-gameplay.cfg&amp;lt;/code&amp;gt;. Lines beginning with &amp;lt;code&amp;gt;//&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are comments.&lt;br /&gt;
&lt;br /&gt;
Sensitive identifiers containing terms such as &amp;lt;code&amp;gt;password&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;secret&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;token&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; are ignored in non-secret files and command-line overrides. Secret layers suppress their command output.&lt;br /&gt;
&lt;br /&gt;
Run authenticated &amp;lt;code&amp;gt;cfg_reload&amp;lt;/code&amp;gt; to reapply the CFG stack and selected ruleset for the current map and mode. It does not synchronize Workshop items, reload manually staged packages, or load &amp;lt;code&amp;gt;server-addons.json&amp;lt;/code&amp;gt;. Restart after changing those inputs. &amp;lt;code&amp;gt;rotation.json&amp;lt;/code&amp;gt; is read by rotation selection rather than by &amp;lt;code&amp;gt;cfg_reload&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Basic server settings ==&lt;br /&gt;
&lt;br /&gt;
Uncomment or add only the values the server needs in &amp;lt;code&amp;gt;config/server.cfg&amp;lt;/code&amp;gt;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
hostname &amp;quot;Toronto Community Server&amp;quot;&lt;br /&gt;
sv_ruleset casual&lt;br /&gt;
&lt;br /&gt;
bot_quota 4&lt;br /&gt;
bot_quota_mode 0&lt;br /&gt;
bot_difficulty 2&lt;br /&gt;
&lt;br /&gt;
mp_timelimit 30&lt;br /&gt;
mp_roundtime 0&lt;br /&gt;
mp_winlimit 0&lt;br /&gt;
mp_maxrounds 0&lt;br /&gt;
sv_match_end_policy 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; lets the active mode supply its default where supported. &amp;lt;code&amp;gt;sv_match_end_policy&amp;lt;/code&amp;gt; accepts &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; for a next-map vote, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; for automatic travel to the next rotation entry, or &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; to quit after the match.&lt;br /&gt;
&lt;br /&gt;
Use the console&amp;#039;s variable help for the current value contract. The generated &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt; also lists common bot, match, security, inventory, and movement settings.&lt;br /&gt;
&lt;br /&gt;
=== Rulesets ===&lt;br /&gt;
&lt;br /&gt;
Community and listen servers default to the bundled &amp;lt;code&amp;gt;casual&amp;lt;/code&amp;gt; ruleset. Put a custom ruleset in &amp;lt;code&amp;gt;config/rulesets/&amp;amp;lt;name&amp;amp;gt;.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
// config/rulesets/community_plus.cfg&lt;br /&gt;
exec rulesets/casual.cfg&lt;br /&gt;
mp_allowspectators 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Select it with &amp;lt;code&amp;gt;sv_ruleset community_plus&amp;lt;/code&amp;gt;. A ruleset supports one console-variable assignment per line, &amp;lt;code&amp;gt;exec rulesets/&amp;amp;lt;name&amp;amp;gt;.cfg&amp;lt;/code&amp;gt; inheritance, blank lines, and comments. It rejects arbitrary commands, nested paths, unknown or sensitive variables, include cycles, and invalid values.&lt;br /&gt;
&lt;br /&gt;
During a live or overtime round, a console change to &amp;lt;code&amp;gt;sv_ruleset&amp;lt;/code&amp;gt; applies at the next round boundary unless the command includes &amp;lt;code&amp;gt;now&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Per-mode and per-map overrides ===&lt;br /&gt;
&lt;br /&gt;
Name each override file with the canonical runtime ID. Map overrides run after mode overrides, so a map can refine a shared mode configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
// config/modes/arena.cfg&lt;br /&gt;
mp_roundtime 12&lt;br /&gt;
bot_quota 6&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
// config/maps/as_compound.cfg&lt;br /&gt;
mp_roundtime 10&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;as_compound&amp;lt;/code&amp;gt; runs in &amp;lt;code&amp;gt;arena&amp;lt;/code&amp;gt;, the round time is 10 because the map file is later in the stack. A map played in another mode still receives its map file. Put an override in &amp;lt;code&amp;gt;autoexec.cfg&amp;lt;/code&amp;gt; only when it must win for every map and mode.&lt;br /&gt;
&lt;br /&gt;
== Message of the day ==&lt;br /&gt;
&lt;br /&gt;
Enable the generated &amp;lt;code&amp;gt;config/motd.html&amp;lt;/code&amp;gt; fragment from &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
sv_motd_enabled 1&lt;br /&gt;
sv_motd_title &amp;quot;Server Rules&amp;quot;&lt;br /&gt;
sv_motd_file &amp;quot;motd.html&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The file is shown after a player joins and before deployment. It may contain inline HTML, CSS, and &amp;lt;code&amp;gt;data:&amp;lt;/code&amp;gt; images or fonts. Scripts, forms, frames, plugins, media, navigation, and network requests are blocked. The title is limited to 128 characters and the HTML payload to 64 KiB. File lookup stays inside the server config root and accepts only &amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; files.&lt;br /&gt;
&lt;br /&gt;
== Bot names and bans ==&lt;br /&gt;
&lt;br /&gt;
Leave &amp;lt;code&amp;gt;config/bots.cfg&amp;lt;/code&amp;gt; blank to use the built-in bot names. To replace them, add one display name per line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Mara&lt;br /&gt;
&amp;quot;Copper Jack&amp;quot;&lt;br /&gt;
Ash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;config/banned_user.cfg&amp;lt;/code&amp;gt; stores one SteamID64 per line. An optional second value is a Unix expiry time; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; means permanent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
# permanent&lt;br /&gt;
76561198000000000 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Authenticated console and RCON commands update the file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
banid &amp;lt;steamid|userid|name&amp;gt; [minutes] [kick]&lt;br /&gt;
removeid &amp;lt;steamid&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A missing or zero duration creates a permanent ban. Use a positive duration for a temporary ban.&lt;br /&gt;
&lt;br /&gt;
== Configure RCON ==&lt;br /&gt;
&lt;br /&gt;
Put RCON settings in &amp;lt;code&amp;gt;secrets/server.secrets.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
rcon_enable 1&lt;br /&gt;
rcon_password &amp;quot;use-a-long-unique-password&amp;quot;&lt;br /&gt;
rcon_port 27015&lt;br /&gt;
rcon_maxclients 3&lt;br /&gt;
rcon_timeout 30&lt;br /&gt;
rcon_failures 3&lt;br /&gt;
rcon_ban_time 300&lt;br /&gt;
rcon_log 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Restrict the secret directory at the operating-system level. Expose the RCON TCP port only to administrator addresses or a private network. Do not reuse the server password or a Steam credential as the RCON password.&lt;br /&gt;
&lt;br /&gt;
== Configure map and mode rotation ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;config/rotation.json&amp;lt;/code&amp;gt; stores map/mode pairs. &amp;lt;code&amp;gt;listMode&amp;lt;/code&amp;gt; defaults to &amp;lt;code&amp;gt;whitelist&amp;lt;/code&amp;gt;, which keeps the declared order:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;listMode&amp;quot;: &amp;quot;whitelist&amp;quot;,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;as_compound&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;map&amp;quot;: &amp;quot;bz_ordainment&amp;quot;,&lt;br /&gt;
      &amp;quot;mode&amp;quot;: &amp;quot;blitz&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;map&amp;quot;: &amp;quot;community_castle&amp;quot;,&lt;br /&gt;
      &amp;quot;mode&amp;quot;: &amp;quot;arena&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;map&amp;quot;: &amp;quot;community_castle&amp;quot;,&lt;br /&gt;
      &amp;quot;mode&amp;quot;: &amp;quot;koth&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use internal map IDs from the installed package manifests. A string is shorthand for an object with a &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; field and no &amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt; field. The same map can appear more than once when each entry has a different mode. Duplicate map/mode pairs are removed.&lt;br /&gt;
&lt;br /&gt;
=== How a mode is selected ===&lt;br /&gt;
&lt;br /&gt;
For each whitelist entry, the server resolves the mode in this order:&lt;br /&gt;
&lt;br /&gt;
# The entry&amp;#039;s explicit &amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt; value.&lt;br /&gt;
# The map entry&amp;#039;s &amp;lt;code&amp;gt;defaultModeId&amp;lt;/code&amp;gt; in its installed &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt; or built-in map data.&lt;br /&gt;
# &amp;lt;code&amp;gt;sandbox&amp;lt;/code&amp;gt; when the map declares no default.&lt;br /&gt;
&lt;br /&gt;
Map ID prefixes are not part of mode selection. A map named &amp;lt;code&amp;gt;bz_example&amp;lt;/code&amp;gt; does not select &amp;lt;code&amp;gt;blitz&amp;lt;/code&amp;gt; unless its map metadata declares that default or the rotation entry supplies &amp;lt;code&amp;gt;&amp;quot;mode&amp;quot;: &amp;quot;blitz&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An explicit mode must be built in or registered by an active VMod before the map starts. Otherwise the mode cannot be activated.&lt;br /&gt;
&lt;br /&gt;
=== Blacklist rotation ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;listMode&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;blacklist&amp;lt;/code&amp;gt; to rotate every registered map except the listed defaults:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;listMode&amp;quot;: &amp;quot;blacklist&amp;quot;,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;as_compound&amp;quot;,&lt;br /&gt;
    &amp;quot;community_ruins&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Blacklist expansion runs after Workshop synchronization. Each registered map contributes one pair using its default mode, and the remaining maps are sorted by internal ID without regard to case. An empty blacklist rotates every registered map. Excluding every map stops startup with an error.&lt;br /&gt;
&lt;br /&gt;
An object entry can exclude an exact map/default-mode pair, but a blacklist cannot assign an alternative mode or add a second pairing. Use a whitelist when a map must run with an override or in several modes.&lt;br /&gt;
&lt;br /&gt;
=== Startup and match transitions ===&lt;br /&gt;
&lt;br /&gt;
Workshop synchronization and add-on loading finish before the final startup map is selected. Missing or unavailable whitelist entries are skipped in file order. Startup fails when no loadable entry remains.&lt;br /&gt;
&lt;br /&gt;
The launch options interact with the saved rotation as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Launch input !! Startup result !! Next rotation result&lt;br /&gt;
|-&lt;br /&gt;
| No map or mode || First loadable entry || Following entry&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--mode &amp;amp;lt;mode&amp;amp;gt;&amp;lt;/code&amp;gt; only || First loadable entry with that mode; startup fails if none exists || Following entry&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--map &amp;amp;lt;map&amp;amp;gt;&amp;lt;/code&amp;gt; || Requested registered map, even when it is outside the rotation || First entry when the active map/mode pair is outside the rotation&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--map &amp;amp;lt;map&amp;amp;gt; --mode &amp;amp;lt;mode&amp;amp;gt;&amp;lt;/code&amp;gt; || Requested pair || Following entry when that exact pair exists; otherwise the first entry&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Use authenticated console or RCON for an immediate manual change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
changelevel &amp;lt;map-id&amp;gt; [mode-id]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Omitting the mode uses the map default, then &amp;lt;code&amp;gt;sandbox&amp;lt;/code&amp;gt;. The saved rotation remains unchanged.&lt;br /&gt;
&lt;br /&gt;
== Install Workshop add-ons ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;config/server-addons.json&amp;lt;/code&amp;gt; controls Workshop acquisition. Store every Steam published-file or collection ID as a JSON string so the 64-bit value cannot lose precision.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Use it when&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;items&amp;lt;/code&amp;gt; || Steam should download a direct Map or Content item for the server.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;collections&amp;lt;/code&amp;gt; || Steam should expand a collection and install its child items.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;manualItems&amp;lt;/code&amp;gt; || A complete Release package is already installed below &amp;lt;code&amp;gt;&amp;amp;lt;data-root&amp;amp;gt;/addons&amp;lt;/code&amp;gt; and must be bound to its client-visible Workshop item.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A combined configuration looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schemaVersion&amp;quot;: 1,&lt;br /&gt;
  &amp;quot;workshop&amp;quot;: {&lt;br /&gt;
    &amp;quot;depotId&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;items&amp;quot;: [&lt;br /&gt;
      &amp;quot;1234567890&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;manualItems&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;publishedFileId&amp;quot;: &amp;quot;2345678901&amp;quot;,&lt;br /&gt;
        &amp;quot;addonId&amp;quot;: &amp;quot;community_castle&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;collections&amp;quot;: [&lt;br /&gt;
      &amp;quot;3456789012&amp;quot;&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;lt;code&amp;gt;depotId&amp;lt;/code&amp;gt; empty unless Vellocet support directs you to change it. Grimwar supplies the dedicated-server depot.&lt;br /&gt;
&lt;br /&gt;
=== Steam-managed items and collections ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;items&amp;lt;/code&amp;gt; contains direct Workshop published-file IDs. The server downloads and updates them through Steam under &amp;lt;code&amp;gt;&amp;amp;lt;data-root&amp;amp;gt;/cache/steam-workshop-server&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;collections&amp;lt;/code&amp;gt; contains Workshop collection IDs. The server resolves the collection and installs its children. A joining client acquires only the package for the active map and any session-wide requirements, not the full server collection.&lt;br /&gt;
&lt;br /&gt;
For container deployments, &amp;lt;code&amp;gt;--workshop-items&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;GRIMWAR_WORKSHOP_ITEMS&amp;lt;/code&amp;gt; adds direct item IDs to the file configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
GrimwarServer --workshop-items=1234567890,2345678901&lt;br /&gt;
GRIMWAR_WORKSHOP_ITEMS=1234567890,2345678901&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comma, semicolon, and whitespace separators are accepted. Collections remain in &amp;lt;code&amp;gt;server-addons.json&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;--workshop-depot-id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GRIMWAR_WORKSHOP_DEPOT_ID&amp;lt;/code&amp;gt; are advanced depot overrides, not normal setup values.&lt;br /&gt;
&lt;br /&gt;
=== Manually staged Workshop package ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;manualItems&amp;lt;/code&amp;gt; binds a local server package to a Workshop item that clients can download. Use it for a mixed package that contains a map or reusable audio plus a VMod, or when the operator manages server files outside Steam.&lt;br /&gt;
&lt;br /&gt;
# Build or obtain the complete, unmodified Release package.&lt;br /&gt;
# Put the directory below &amp;lt;code&amp;gt;&amp;amp;lt;data-root&amp;amp;gt;/addons&amp;lt;/code&amp;gt;. The package root itself must contain &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Read the package &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;buildId&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Add its Workshop published-file ID and manifest add-on ID to &amp;lt;code&amp;gt;manualItems&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Remove the same published-file ID from &amp;lt;code&amp;gt;items&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Restart the server and inspect &amp;lt;code&amp;gt;[ServerWorkshop]&amp;lt;/code&amp;gt; logs.&lt;br /&gt;
&lt;br /&gt;
Example layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
/srv/grimwar/community-1/&lt;br /&gt;
  addons/&lt;br /&gt;
    community_castle/&lt;br /&gt;
      addon.json&lt;br /&gt;
      mod.json&lt;br /&gt;
      CommunityCastle.csx&lt;br /&gt;
      maps/&lt;br /&gt;
  config/&lt;br /&gt;
    server-addons.json&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The local server package and client-visible Workshop package must have the same add-on ID and build ID. Map and VMod uploads include declared server source; map-bound snapshots remain inside the compiled scene. Clients do not execute it. Replace the staged server package every time the Workshop item is rebuilt.&lt;br /&gt;
&lt;br /&gt;
One published-file ID may appear in &amp;lt;code&amp;gt;items&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;manualItems&amp;lt;/code&amp;gt;, never both. Duplicate published-file IDs or add-on IDs in &amp;lt;code&amp;gt;manualItems&amp;lt;/code&amp;gt; make the configuration invalid.&lt;br /&gt;
&lt;br /&gt;
Clients do not download files from &amp;lt;code&amp;gt;&amp;amp;lt;data-root&amp;amp;gt;/addons&amp;lt;/code&amp;gt;. They receive the sanitized Map or Content item from Steam and verify its published-file ID, add-on ID, and exact build ID. The current Workshop visibility must allow those clients to access it.&lt;br /&gt;
&lt;br /&gt;
When every configured identity uses &amp;lt;code&amp;gt;manualItems&amp;lt;/code&amp;gt;, the server does not request a Workshop download. A collection still requires Steam so the server can query its children.&lt;br /&gt;
&lt;br /&gt;
See [[Grimwar/Steam Workshop addons#How Grimwar identifies maps and content|How Grimwar identifies maps and content]] for the manifest fields that distinguish a map from reusable content. Put every installed map ID used by the server in a whitelist rotation. Blacklist rotation considers installed maps automatically.&lt;br /&gt;
&lt;br /&gt;
== Install VMods ==&lt;br /&gt;
&lt;br /&gt;
# Run &amp;lt;code&amp;gt;vmod_runtime_paths&amp;lt;/code&amp;gt; and use the printed add-on directory.&lt;br /&gt;
# Copy the complete VMod add-on folder below &amp;lt;code&amp;gt;&amp;amp;lt;data-root&amp;amp;gt;/addons&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Restart, or run &amp;lt;code&amp;gt;vmod_runtime_reload&amp;lt;/code&amp;gt; while no scripted mode is active.&lt;br /&gt;
# Confirm the package with &amp;lt;code&amp;gt;vmod_runtime_list&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
VMod-only packages are server-only and are installed manually. A mixed package can publish its map or audio to Workshop, but the server still needs the complete package. Admin users, groups, and external capability grants live below &amp;lt;code&amp;gt;&amp;amp;lt;data-root&amp;amp;gt;/config/mods&amp;lt;/code&amp;gt;. See [[Grimwar/VMod|VMod scripting and administration]].&lt;br /&gt;
&lt;br /&gt;
== Startup and diagnostics ==&lt;br /&gt;
&lt;br /&gt;
Before opening the server publicly:&lt;br /&gt;
&lt;br /&gt;
# Run preflight with the production data directory.&lt;br /&gt;
# Start the server and confirm it reaches its ready/listening state.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;status -v&amp;lt;/code&amp;gt; and verify the &amp;lt;code&amp;gt;community&amp;lt;/code&amp;gt; role, &amp;lt;code&amp;gt;steam-relay&amp;lt;/code&amp;gt; transport, build, protocol, map, mode, ruleset, data path, and player limit.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;cfg_paths&amp;lt;/code&amp;gt; and confirm the data, config, secret, and add-on roots.&lt;br /&gt;
# Confirm each Workshop or manual item loaded and every rotation map registered.&lt;br /&gt;
# Join with a separate Steam account and test authentication, required-content delivery, round transition, and map change.&lt;br /&gt;
# Test RCON from an allowed administrator address.&lt;br /&gt;
&lt;br /&gt;
Useful log prefixes are:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Prefix !! Check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[ServerWorkshop]&amp;lt;/code&amp;gt; || Server configuration, manual bindings, collection expansion, downloads, validation, and activation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[AddonCatalog]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;[AddonLoader]&amp;lt;/code&amp;gt; || Package selection, validation, dependencies, and runtime loading.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[ServerRotation]&amp;lt;/code&amp;gt; || Unknown entries, selected map/mode pairs, and next-map resolution.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[WorkshopDL]&amp;lt;/code&amp;gt; || Exact client/server published-file, add-on, and build matching.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[SteamWorkshop]&amp;lt;/code&amp;gt; || Steam installation and update state.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[ContentDL]&amp;lt;/code&amp;gt; || Content provider selection and completion.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[Net]&amp;lt;/code&amp;gt; || Pre-login requirements; set &amp;lt;code&amp;gt;net_log 2&amp;lt;/code&amp;gt; for per-add-on identities.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Do not add a public gameplay mapping when preflight or Steam startup fails. Fix the reported Steam login, credential, port conflict, package, or network error first.&lt;br /&gt;
&lt;br /&gt;
Back up the data directory before game or add-on updates. It contains operator configuration, VMod state, source selections, bans, and other mutable server data. The game installation is not a substitute for that backup.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:Dedicated servers]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
</feed>