og-cod-plutainer/tools
Amos d117dede7d
feat: CoD4x support, headless T7x, unauthenticated healthcheck, log rotation
Six pieces of work that turned out to share a lot of ground.

T7x no longer needs Xvfb. Passing -headless makes it skip Sys_CreateConsole and
print to stdout instead of building a Win32 console window, which is the only
reason a display was ever required. Verified against a clean volume; the images
now ship no X server at all, saving ~340MB.

Seed configs are vendored under seed-configs/ instead of being wget'd from six
third-party repos at build time. Any one of those disappearing broke the build
for every game, and alterware/t7x 404'd while this was being written. The RUN
string never changed either, so BuildKit cached the layer indefinitely and
upstream edits stayed invisible. tools/refresh-seeds.sh pins each repo to a
commit, records it in seed-configs/<game>/SOURCE, and blanks the placeholder
credentials upstream ships (an RCON password everyone knows, and in cod4x's case
a g_password that locked players out).

The healthcheck no longer needs an RCON password. It asks the server for its
status and requires a loaded map, trying getstatus then getinfo: IW5 and T5 only
answer the latter, while T7x's getinfo reports the lobby's map rather than the
running one. Every bundled config ships rcon_password empty, so the old
RCON-based check could never pass on a first run. pyquake3 is trimmed to the two
paths actually used, and now tolerates the stray byte T7x prefixes to its
statusResponse - which is why RCON never worked on T7x at all.

T5 and T6 gate unauthenticated getinfo on the RCON whitelist, so a sidecar
IW4MAdmin completes the RCON handshake and then fails on unanswered getinfo. The
sender is the container's Docker gateway, assigned at runtime, so it cannot be
written into a config file: resolve_rcon_whitelist_args detects it and passes
+rconWhitelistAdd. PLUTAINER_RCON_PASSWORD writes a password into the config,
opt-in and never destructive.

CoD4x is new, and is the one family that does not use Wine - upstream ships a
native Linux server, and the Windows build dies at window creation exactly as
T7x did. That makes it amd64-only, since the binary is 32-bit x86. Two assets
come from the client release because the server release has no fastfiles.

Game logs are rotated at 64MB. A large enough log stops CoD4x logging
permanently: the writer hands each chunk to fwrite, and on failure prints a
warning and drops the data with the buffer already advanced. Rotation is
copy-truncate, safe because every engine opens its log with fopen(path, "ab").
A marker line is written after truncating, and into any empty log, because
IW4MAdmin treats a zero offset as "no position yet" and re-syncs instead of
reading - which silently swallowed the first batch of events after each
rotation, and the first map's events on every fresh deployment.

Also fixes the arm64 healthcheck start period, which was 1m against amd64's 5m
and would have marked a first-run IW4x download unhealthy mid-download, and
bumps Hangover 11.4 -> 11.9.
2026-08-15 17:22:14 +01:00
..
refresh-seeds.sh feat: CoD4x support, headless T7x, unauthenticated healthcheck, log rotation 2026-08-15 17:22:14 +01:00