og-cod-plutainer/docs/quickstart.md
Amos 275c4c06d9
docs: correct the CoD4x key situation
"No key" was misleading. CoD4x has no Plutonium-style key, but a public server
does need a masterserver token: without one it cannot register, and an
unregistered server never appears in the in-game server browser, so in practice
nobody finds it. Only players given the address can connect directly. Host
migration needs one too.

The engine documents the source itself - sv_authtoken is registered with the
description "Token to register on masterserver. You can get it from
http://cod4master.cod4x.ovh" - and validates it at 32 characters. Both are now
in the docs, along with what actually happens when it is absent.

Corrected in the README game table, the games at-a-glance table, the quickstart
prerequisites, the variable reference, the troubleshooting entry, and both
examples. IW4x and T7x really do need nothing and are left as they were.
2026-08-15 18:01:04 +01:00

3.8 KiB
Raw Blame History

Quickstart

Getting one server running, start to finish. Budget ten minutes, most of it waiting for downloads.

Before you start

You need three things:

  1. Docker and Docker Compose on a Linux host.
  2. The base game files, which you must own. Plutainer ships no game content. What exactly each game needs is in Games.
  3. A server key or token, depending on the game:

1. Put the game files somewhere

Anywhere on the host. They're mounted read-only, so they can be shared by as many servers as you like:

/opt/game-files/
  T6ServerFiles/
  IW4xServerFiles/

2. Write a compose file

Pick your game's example from examples/, or start from this one:

services:
  t6zm-1:
    image: ghcr.io/ayymoss/plutainer:latest
    container_name: t6zm-1
    restart: unless-stopped
    ports:
      - "4976:4976/udp"
    volumes:
      - /opt/game-files/T6ServerFiles:/home/plutainer/gamefiles:ro
      - ./t6zm-1:/home/plutainer/app
    environment:
      PLUTAINER_GAME: t6zm
      PLUTAINER_CONFIG_FILE: dedicated_zm.cfg
      PLUTO_SERVER_KEY: ${T6ZM_KEY}
      PLUTAINER_RCON_PASSWORD: change-me-or-remove-this-line

Four settings matter:

PLUTAINER_GAME Which game. Full list
PLUTAINER_CONFIG_FILE Which config to run. Must be one Plutainer seeds unless you supply your own — names per game
the gamefiles mount Your base game files, read-only
the app mount Where server data, configs and logs live

Put the key in a .env file next to your compose file so it stays out of the compose:

T6ZM_KEY=your-key-here

3. Start it

docker compose up -d
docker compose logs -f

First start takes a while. Plutonium downloads ~500 MB, IW4x 12 GB. CoD4x is ready in under a minute since everything ships in the image. The healthcheck allows five minutes before it starts judging.

4. Check it worked

docker ps

healthy means the server answered a status query and reported a loaded map — it's genuinely up, not just running. If it says unhealthy or never leaves starting, go to Troubleshooting.

5. Edit your config

Everything is in one folder, whatever the game:

nano ./t6zm-1/configs/dedicated_zm.cfg
docker restart t6zm-1

Plutainer symlinks that file to wherever the engine expects it, so you never go hunting through runtime/. Details in Volumes & configs.

What you get

t6zm-1/
  configs/          ← edit your *.cfg here
  logs/             ← stable symlinks to the live logs
  runtime/          ← game files, binaries, engine state (leave alone)

Next steps

  • Send commands to the serverRCON. Set PLUTAINER_RCON_PASSWORD first; it's empty by default so RCON is off.
  • Add an admin toolIW4MAdmin
  • Run several serversexamples/multi-server.yml. Each needs its own port and its own app directory; the gamefiles mount can be shared.
  • Restart servers automatically when they dieHealthcheck & restarts

A note on permissions

The container runs as UID 1000. If you create the app directory as root, the container may not be able to write to it:

sudo chown -R 1000:1000 ./t6zm-1

Most desktop Linux users are already UID 1000 and never hit this. If the logs say Permission denied while creating configs, logs or runtime, this is why.