Skip to content

Instantly share code, notes, and snippets.

@simi
Last active July 28, 2026 08:46
Show Gist options
  • Select an option

  • Save simi/dc4fbc68179658255ced73d2da15378b to your computer and use it in GitHub Desktop.

Select an option

Save simi/dc4fbc68179658255ced73d2da15378b to your computer and use it in GitHub Desktop.
CWR Server guide

Running a public CWR dedicated server


Install CWR through Steam or GOG and open the game's installation directory. The dedicated server is included with the normal game installation: use PoseidonServer on Linux or PoseidonServer.exe on Windows. For a remote host, copy the complete installation to it. The server needs no Steam/GOG client, account login, or CD key at runtime.

Examples use /srv/cwr as the Linux game directory and C:\CWR as the Windows game directory. The game directory contains the server and installed game data:

<game directory>/
├── PoseidonServer or PoseidonServer.exe
├── AddOns/
├── BIN/
├── DTA/
├── MPMissions/
└── Worlds/

Quick start

1. Create server.cfg

Save this as server.cfg in the game directory:

hostname = "My CWR server";
password = "";
passwordAdmin = "set-a-strong-password";
maxPlayers = 16;
  • hostname is the name shown in the server browser.
  • password is the password players enter to join. Leave it empty for an open server.
  • passwordAdmin is used with #login to gain server-admin commands. It does not restrict joining.
  • maxPlayers is the maximum number of players who can join and play.

With no mission rotation configured, the server opens mission selection when the first player joins.

2. Open the network port

The default CWR server port is UDP 1985. Only UDP is needed for game traffic and voice; no separate voice port is required.

Allow inbound UDP 1985 in every firewall between the internet and the server:

  • the operating-system firewall;
  • a hosting-provider or cloud firewall/security group; and
  • the router, if the server is behind NAT.

On a Linux host using UFW:

sudo ufw allow 1985/udp

On a Linux host using firewalld:

sudo firewall-cmd --permanent --add-port=1985/udp
sudo firewall-cmd --reload

On Windows, run PowerShell as Administrator:

New-NetFirewallRule -DisplayName 'CWR Dedicated Server UDP 1985' -Direction Inbound -Protocol UDP -LocalPort 1985 -Action Allow

Behind NAT, forward UDP 1985 to the host. A connection behind carrier-grade NAT needs a public address or port mapping from the provider. Allow outbound HTTPS/TCP 443 to papa-bear.cz for the Internet listing.

Run the server from the game directory. --config server.cfg loads the file created above; it is not loaded automatically. --public opts into the Internet listing. CWR already defaults to papa-bear.cz, UDP 1985, all IPv4 interfaces, and automatic public-address detection.

3. Start the server on Linux

cd /srv/cwr
./PoseidonServer --config server.cfg --public

4. Start the server on Windows

cd C:\CWR
.\PoseidonServer.exe --config server.cfg --public

5. Check that it works

The server logs to the terminal. Add --log-file server.log to keep a text log file in the game directory.

The startup log contains:

Server initialized successfully on port 1985
Master-server publish address: <address>:1985
Dedicated server main loop started

Start the game, open Multiplayer → Internet, and search for the configured hostname. You can also test a direct connection to <public-ip>:1985. Select a mission, then verify that the player reaches role selection, briefing, and the mission and can move normally.

Press Ctrl+C in the server terminal to stop it. A logged-in server admin can also use #shutdown from game chat.

Adding missions

Copy multiplayer mission PBOs to the game's MPMissions/ directory and restart the server. They then appear in mission selection. Missions supplied by a mod must also be packed as PBOs; keep them in that mod's MPMissions/ directory and enable the mod when starting the server.

Adding mods

Put each downloaded mod folder below one common mods/ directory:

<game directory>/
└── mods/
    ├── mfcti-1.16/
    │   ├── AddOns/
    │   └── MPMissions/
    └── 80-islands-1.3/
        └── AddOns/

Then add these options to either launch command:

--mods-dir mods --mod "mfcti-1.16;80-islands-1.3"

In PowerShell:

--mods-dir mods --mod 'mfcti-1.16;80-islands-1.3'

Relative paths are resolved from the directory where the server starts. The launch examples start in the game directory, so mods refers to its mods/ folder. --mods-dir also accepts an absolute path. --mod enables and orders the folders below it.

Players use the corresponding client mods. To require the same advertised mod list, add this to server.cfg:

equalModRequired = 1;

Server administration

Join the server from a game client and enter this in chat:

#login set-a-strong-password

Useful admin commands are:

Command Effect
#logout Give up admin control.
#userlist Show player numbers, names, IDs, and pings; no admin login is required.
#kick NAME_OR_NUMBER Disconnect a player.
#ban NAME_OR_NUMBER Ban and disconnect a player.
#unban PLAYER_ID_OR_IPV4 Remove a dynamic ID or IP ban.
#restart Restart the current playing mission.
#reassign Restart and return everyone to role selection.
#missions Open mission selection.
#mission 1-8_D_FlagFight.ABEL Select a mission by its exact Name.World name, without .pbo.
#monitor 10 Show server FPS, memory use, and network traffic in the admin's chat every ten seconds; #monitor 0 stops.
#shutdown Cleanly stop the dedicated server; requires a password-admin login.

Ten failed admin-password attempts cause a kick.

Player voting commands

When no admin controls the server, players can vote through chat:

#vote kick NAME_OR_NUMBER
#vote restart
#vote reassign
#vote missions
#vote admin NAME_OR_NUMBER

These votes are controlled by voteThreshold in server.cfg. A voted admin can moderate players and control missions, but cannot use #shutdown; that command requires #login with passwordAdmin.

More server.cfg settings

These settings can be added to server.cfg:

voiceOverNet = 1;
equalModRequired = 0;
kickDuplicate = 1;
banMode = "both";
MaxCustomFileSize = 131072;

motdInterval = 5;
motd[] =
{
    "Welcome to my CWR server",
    "Have fun"
};

voteThreshold = 0.5;
voteMissionPlayers = 1;
Setting Meaning
hostname Name shown in the browser.
password Password players enter to join; empty allows passwordless joining. It overrides CLI --password when present.
passwordAdmin Password used with #login to gain server-admin commands; empty or missing disables password-based admin login.
maxPlayers Maximum number of players who can join and play.
voiceOverNet 1 enables built-in voice; 0 disables it.
equalModRequired Require clients to advertise the same ordered mod identifiers.
kickDuplicate Kick a joining duplicate player identity.
banMode What #ban records: id, ip, or both. Default is both.
MaxCustomFileSize Maximum custom face/radio-sound size in bytes; default 131072, 0 blocks them.
motd[] Messages sent to a joining player.
motdInterval Seconds between MOTD messages; default 5.
voteThreshold Fraction of connected players that votes must exceed; default 0.5 means a majority.
voteMissionPlayers Players required before mission selection is offered without a rotation; default 1.
Missions Ordered rotation. Each item accepts template, cadetMode, and optional param1/param2.

Restart the process after editing server.cfg.

Automatic mission rotation

By default, the first joining player selects a mission. To start missions automatically and cycle through a playlist, add this to server.cfg:

class Missions
{
    class Item0
    {
        template = "2-8_T_RealPaintball.intro";
        cadetMode = 0;
    };

    class Item1
    {
        template = "1-8_D_FlagFight.ABEL";
        cadetMode = 0;
    };
};

template is the exact mission name, including its world suffix, but without a final .pbo. Entries run in order as missions end. cadetMode = 0 selects veteran mode; cadetMode = 1 selects cadet mode. Rotation entries may also set param1 and param2.

Difficulty options

cadetMode selects a difficulty column; the individual options are stored in difficulty.cfg for the operating-system account that runs the server:

Server setup difficulty.cfg location
Linux default ${XDG_CONFIG_HOME:-$HOME/.config}/CWR/difficulty.cfg
Windows default %APPDATA%\CWR\difficulty.cfg
POSEIDON_USER_DIR is set Directly inside that directory

The following is the default configuration:

diffArmor[]={1,0};
diffFriendlyTag[]={1,0};
diffEnemyTag[]={0,0};
diffHUD[]={1,0};
diffAutoSpot[]={1,0};
diffMap[]={1,0};
diffWeaponCursor[]={1,1};
diffAutoGuideAT[]={1,0};
diffClockIndicator[]={1,1};
diff3rdPersonView[]={1,1};
diffTracers[]={1,1};
diffUltraAI[]={0,0};

Each pair is {cadet,veteran}: 1 enables the option and 0 disables it. For example, diff3rdPersonView[]={1,0}; allows third-person view in cadet mode and disables it in veteran mode. The keys correspond to these in-game options:

Key Option
diffArmor Extended armor
diffFriendlyTag Friendly tag
diffEnemyTag Enemy tag
diffHUD Extended HUD information
diffAutoSpot Automatic reporting
diffMap Extended map information
diffWeaponCursor Weapon crosshair
diffAutoGuideAT Automatic anti-tank guidance
diffClockIndicator Clock-direction indicator
diff3rdPersonView Third-person view
diffTracers Rifle bullet tracers
diffUltraAI Super AI

In a mission rotation, cadetMode = 1 uses the first value of every pair and cadetMode = 0 uses the second. With manual mission selection, the selected Cadet or Veteran mode chooses the same column. The server sends those options to joining clients and overrides their local difficulty options for that multiplayer mission.

Restart the server after editing difficulty.cfg. Include every key in the file: once it exists, omitted keys use the built-in defaults rather than values from a player profile. CWR uses the original OFP diffName[]={cadet,veteran} format; ArmA-style class Difficulties blocks and skillFriendly / precisionEnemy settings are not supported.

Useful command-line options

Option Meaning
-C DIR, --work-dir DIR Game directory when starting the server from somewhere else.
--config FILE Dedicated-server configuration file.
--public Publish to the Internet directory; off by default.
--private, --lan Force a private/LAN server; omitting --public is already private.
--master-server URL Override the default directory service, https://papa-bear.cz.
--advertise-address HOST Override the automatically detected public IP address or hostname; do not include the port.
--port N UDP game/query port; default 1985.
--bind-address IPv4 Local interface; default 0.0.0.0 means all IPv4 interfaces.
--mods-dir DIR Parent directory used to resolve mod names; relative to the directory where the server starts.
--mod LIST Semicolon-separated enabled mods. Quote the complete list.
--password VALUE Join-password fallback when password is absent from server.cfg.
--log-file FILE Write logs to a file as well as the terminal.
--log-level LEVEL trace, debug, info, warn, error, critical, or off.
--log-format text|jsonl Terminal output as human-readable text or one JSON record per line; --log-file remains text.
--pid FILE Write the running process ID for management scripts.
--max-threads N Task-thread count; automatic mode caps at 8, while 0 uses all logical cores.
--help, --help-full Show the options supported by the installed version.
--version, --mp-version Show the game or multiplayer compatibility version and exit.

Private/LAN server

From the game directory, omit --public to start a private server:

./PoseidonServer --config server.cfg

For a same-machine-only test, use --bind-address 127.0.0.1.

Multiple server instances

Each instance needs its own UDP port, server.cfg, and log file. Open and forward the chosen UDP port consistently. Separate state directories keep profiles, bans, and temporary files apart:

mkdir -p /srv/cwr/state/server2/user /srv/cwr/state/server2/cache /srv/cwr/state/server2/temp
export POSEIDON_USER_DIR=/srv/cwr/state/server2/user
export POSEIDON_CACHE_DIR=/srv/cwr/state/server2/cache
export POSEIDON_TEMP_DIR=/srv/cwr/state/server2/temp

Use the equivalent $env:POSEIDON_USER_DIR, $env:POSEIDON_CACHE_DIR, and $env:POSEIDON_TEMP_DIR variables in PowerShell.

Troubleshooting

  • The server is not in Multiplayer → Internet: confirm --public, outbound HTTPS, and Master-server publish address in the log. If the directory cannot detect the host's public address, set --advertise-address explicitly.
  • The server is listed but nobody can join: fix the OS/cloud firewall and router port-forward for UDP 1985. Publishing does not prove the UDP port is reachable.
  • The config is ignored: start the process in the game directory and look for Server config loaded: in the log. Use -C only when launching from another directory.
  • The requested port is busy: stop the conflicting process or use the same new UDP port in the launch command, firewalls, and router forward. The log reports the port actually bound by the server.
  • A mission is not found: confirm its folder or PBO exists in the base MPMissions/, or its PBO exists in an enabled mod's MPMissions/. The template must match its exact Name.World name without the final .pbo.
  • A mod is not loaded: confirm the folder is directly below --mods-dir, is named in --mod, and that the semicolon-separated list is quoted.
  • Clients fail the mod check: start the server and clients with the same mods in the same order, or set equalModRequired = 0.
  • Linux reports Permission denied: run chmod +x PoseidonServer once.
@SrapNZ

SrapNZ commented Jul 28, 2026

Copy link
Copy Markdown

Hello, will the respawn function also be fixed. We've had problems where respawning to group simply spawns us as an AI with no control. Revive is also broken too. All players crash to Desktop when about to enter revive state.

Thanks guys, love your work!

@simi

simi commented Jul 28, 2026

Copy link
Copy Markdown
Author

Hello @SrapNZ. Sad to hear you're facing those issues. Would you mind to share more or even open issue at https://github.com/ofpisnotdead-com/CWR-CE with more details? Mission, mods, ... so we can reproduce and fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment