first boot of cm2network/steamcmd: running and quiet for 120s after 180s; stopped gracefully
boot test with the node-agent: PASSED: READY: 10/25/2026 21:32:58: Loading: Done. Total seconds sinze ZNet start: 38.590215, Genloc duration: 30912.942 ms, (Total genloc time: 00:00:31.1144350, locations: 183, iterations: 0)
Notes from research: Crossplay is enabled with the -crossplay launch flag (allows Xbox, PS5, Switch 2, and Game Pass players to join; a join code is printed to the server log). BepInEx and ValheimPlus mods are supported via the lloesche and community-valheim-tools images. Server password must be at least 5 characters or valheim_server.x86_64 refuses to start. There is no config file; all settings are launch arguments. World data lives in a worlds/ subfolder under the -savedir path. Granting CAP_SYS_NICE is optional but avoids a thread-priority warning. The pfeiffermax image explicitly runs as a non-root user; lloesche and community-valheim-tools images also support non-root operation. First start downloads ~1 GB from Steam.
Drafted by the GBR AI builder. **Review before merging**: check the settings, ports and descriptions against the game's documentation.
- Game: **Valheim** — Valheim Dedicated Server
- Image: `cm2network/steamcmd`, Steam app 896660
- Model rounds: 1
**Checked for real**
- image cm2network/steamcmd exists
- image lloesche/valheim-server exists
- image ghcr.io/community-valheim-tools/valheim-server exists
- image pfeiffermax/valheim-dedicated-server exists
- Steam app 896660 is "Valheim Dedicated Server"
- first boot of cm2network/steamcmd: running and quiet for 120s after 180s; stopped gracefully
- boot test with the node-agent: PASSED: READY: 10/25/2026 21:32:58: Loading: Done. Total seconds sinze ZNet start: 38.590215, Genloc duration: 30912.942 ms, (Total genloc time: 00:00:31.1144350, locations: 183, iterations: 0)
**Notes from research:** Crossplay is enabled with the -crossplay launch flag (allows Xbox, PS5, Switch 2, and Game Pass players to join; a join code is printed to the server log). BepInEx and ValheimPlus mods are supported via the lloesche and community-valheim-tools images. Server password must be at least 5 characters or valheim_server.x86_64 refuses to start. There is no config file; all settings are launch arguments. World data lives in a worlds/ subfolder under the -savedir path. Granting CAP_SYS_NICE is optional but avoids a thread-priority warning. The pfeiffermax image explicitly runs as a non-root user; lloesche and community-valheim-tools images also support non-root operation. First start downloads ~1 GB from Steam.
**Sources**
- https://hub.docker.com/r/lloesche/valheim-server
- https://github.com/community-valheim-tools/valheim-server-docker
- https://steamdb.info/app/896660/info/
- https://max-pfeiffer.github.io/how-to-set-up-a-valheim-dedicated-server-using-docker-and-docker-compose.html
- https://hosthavoc.com/wiki/game-servers/valheim/enable-crossplay
- https://www.valheimgame.com/support/a-guide-to-dedicated-servers/
- https://netrouting.com/gaming-industry/setup-valheim/
- https://shattered.io/valheim-dedicated-server/
- https://connecthosting.net/blog/valheim-dedicated-server-setup-guide
- https://www.gameserverkings.com/knowledge-base/valheim/configuration-overview/
- https://natchecker.com/blog/valheim-dedicated-server-port-forwarding
Bash array syntax in defaultStartupCommand may not work in all shells.
The startup command uses bash-specific array syntax (args=(...), args+=(...), "${args[@]}"). If the platform invokes this with /bin/sh (dash, busybox ash, etc.) rather than /bin/bash, the command will fail immediately. Please verify that the cm2network/steamcmd image's /bin/sh is actually bash, or that the platform explicitly execs via bash -c. If it's dash, you'd need to rewrite as a simple positional-argument list or use a different construction.
Config-to-env-var mapping for Crossplay and MaxPlayers needs verification.
The schema keys are Crossplay and MaxPlayers, but the startup command reads ${CROSSPLAY} and ${MAX_PLAYERS}. This implies the platform performs a PascalCase → SNAKE_CASE conversion (and boolean → lowercase string). This isn't obvious from the diff alone. Please confirm the platform's configSchema → environment variable naming convention actually produces CROSSPLAY and MAX_PLAYERS from those keys. A mismatch here would silently disable crossplay and max-players (the [ ... ] guards would just evaluate to false/empty), making the settings appear to work but have no effect.
2. Non-blocking suggestions
ServerPassword schema is missing minLength enforcement.
The description says "Must be at least 5 characters if set" and the notes confirm the binary refuses to start with shorter passwords, but the schema has no minLength. A user who types a 3-char password will get a crash-loop with no UI-level hint. Consider:
MaxPlayers has no bounds.
Add minimum: 1 and maximum: 32 (or whatever Valheim's hard cap is) so the UI can reject nonsensical values before the server tries to start.
Port 2457/udp — please double-check.
Valheim's official and most community sources list only 2456/udp for the dedicated server. I couldn't find a reliable reference to 2457/udp being required. If it's not needed, an extra UDP port widens the attack surface for no benefit. If it is needed (e.g., for a query/discovery protocol), a short comment in the YAML would help future reviewers.
requiredDiskMb: 4096 may be tight.
The PR notes mention ~1 GB Steam download plus world data in worlds/. A single world can grow several GB with biomes, builds, and the genloc data. 4 GB minimum leaves little headroom for a 10-player world. Consider 8192 (8 GB) unless the platform enforces separate volume sizing.
Minor: appId is a quoted string "896660".
This is correct if the schema requires a string, but worth a quick check that the installConfig.appId schema type matches (string vs integer) to avoid a validation failure in stricter parsers.
3. Tests
The boot test (test.yaml) exercises the default config (no password, no crossplay, default world name). Consider adding a second scenario or at least noting in the PR that crossplay enabled and password set paths were not CI-verified. The [ -n "${SERVER_PASSWORD}" ] and [ "${CROSSPLAY}" = "true" ] branches are untested by the harness as written.
The readyPattern is validated against the readyExample, but a regression test that asserts the pattern does not match a partial/loading line (e.g., "Loading: 45%…") would guard against a future log-format change causing false readiness.
4. Overall assessment
The configuration is well-researched, the ready pattern correctly accounts for Valheim's "sinze" typo, and the test setup is reasonable. The two items that need confirmation before merge are the shell compatibility of the bash array syntax and the config-key → env-var naming convention for Crossplay/MaxPlayers — both are silent-failure risks that would only surface at runtime for end users. The schema validation gaps (password length, player bounds) are worth fixing but are UX polish rather than correctness bugs. Once those two verifications are confirmed, this is ready to merge.
Automated review by AI Git Bot
## 🤖 AI Code Review
## 1. Blocking issues
**Bash array syntax in `defaultStartupCommand` may not work in all shells.**
The startup command uses bash-specific array syntax (`args=(...)`, `args+=(...)`, `"${args[@]}"`). If the platform invokes this with `/bin/sh` (dash, busybox ash, etc.) rather than `/bin/bash`, the command will fail immediately. Please verify that the cm2network/steamcmd image's `/bin/sh` is actually bash, or that the platform explicitly execs via `bash -c`. If it's dash, you'd need to rewrite as a simple positional-argument list or use a different construction.
**Config-to-env-var mapping for `Crossplay` and `MaxPlayers` needs verification.**
The schema keys are `Crossplay` and `MaxPlayers`, but the startup command reads `${CROSSPLAY}` and `${MAX_PLAYERS}`. This implies the platform performs a PascalCase → SNAKE_CASE conversion (and boolean → lowercase string). This isn't obvious from the diff alone. Please confirm the platform's `configSchema` → environment variable naming convention actually produces `CROSSPLAY` and `MAX_PLAYERS` from those keys. A mismatch here would silently disable crossplay and max-players (the `[ ... ]` guards would just evaluate to false/empty), making the settings appear to work but have no effect.
## 2. Non-blocking suggestions
**ServerPassword schema is missing `minLength` enforcement.**
The description says "Must be at least 5 characters if set" and the notes confirm the binary refuses to start with shorter passwords, but the schema has no `minLength`. A user who types a 3-char password will get a crash-loop with no UI-level hint. Consider:
```yaml
ServerPassword:
...
anyOf:
- const: ""
- type: string
minLength: 5
```
**MaxPlayers has no bounds.**
Add `minimum: 1` and `maximum: 32` (or whatever Valheim's hard cap is) so the UI can reject nonsensical values before the server tries to start.
**Port 2457/udp — please double-check.**
Valheim's official and most community sources list only **2456/udp** for the dedicated server. I couldn't find a reliable reference to 2457/udp being required. If it's not needed, an extra UDP port widens the attack surface for no benefit. If it *is* needed (e.g., for a query/discovery protocol), a short comment in the YAML would help future reviewers.
**`requiredDiskMb: 4096` may be tight.**
The PR notes mention ~1 GB Steam download plus world data in `worlds/`. A single world can grow several GB with biomes, builds, and the `genloc` data. 4 GB minimum leaves little headroom for a 10-player world. Consider 8192 (8 GB) unless the platform enforces separate volume sizing.
**Minor: `appId` is a quoted string `"896660"`.**
This is correct if the schema requires a string, but worth a quick check that the `installConfig.appId` schema type matches (string vs integer) to avoid a validation failure in stricter parsers.
## 3. Tests
- The boot test (`test.yaml`) exercises the default config (no password, no crossplay, default world name). Consider adding a second scenario or at least noting in the PR that **crossplay enabled** and **password set** paths were not CI-verified. The `[ -n "${SERVER_PASSWORD}" ]` and `[ "${CROSSPLAY}" = "true" ]` branches are untested by the harness as written.
- The `readyPattern` is validated against the `readyExample`, but a regression test that asserts the pattern does **not** match a partial/loading line (e.g., "Loading: 45%…") would guard against a future log-format change causing false readiness.
## 4. Overall assessment
The configuration is well-researched, the ready pattern correctly accounts for Valheim's "sinze" typo, and the test setup is reasonable. The two items that need confirmation before merge are the **shell compatibility** of the bash array syntax and the **config-key → env-var naming convention** for `Crossplay`/`MaxPlayers` — both are silent-failure risks that would only surface at runtime for end users. The schema validation gaps (password length, player bounds) are worth fixing but are UX polish rather than correctness bugs. Once those two verifications are confirmed, this is ready to merge.
---
*Automated review by AI Git Bot*
The draft passed -maxplayers, which the server ignores (Valheim's limit is
fixed), so changing the setting would do nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If the platform (or the cm2network/steamcmd image) invokes this command via /bin/sh (dash, busybox ash), the args=(...) assignment will produce a syntax error and the container will exit immediately. The boot test passing suggests this works in the CI environment, but please confirm:
The image's /bin/sh symlink points to bash, or
The platform's runner explicitly executes startup commands via bash -c '…'.
If neither is guaranteed, the command would need to be rewritten as a flat argument list (e.g., building a positional-parameter string, or using eval). This is a one-time check; if confirmed, no code change is needed.
2. Non-blocking suggestions
Port 2457/udp — please confirm it's actually required.
Most Valheim documentation (official guide, SteamDB, the lloesche and community-valheim-tools repos) lists only 2456/udp. A small number of hosting wikis mention 2457 as a query/heartbeat port, but I couldn't find an authoritative source for it. If it's not needed, removing it reduces the exposed attack surface. If it is needed, a brief inline comment (# query/heartbeat (source: …)) would help future maintainers.
ServerPassword schema could enforce minLength: 5.
The description documents the 5-char minimum, but the schema doesn't reject a 3-char value. The server will crash-loop, and the user sees an opaque error. Suggested schema:
requiredDiskMb: 4096 may be tight for larger worlds.
~1 GB Steam download + world generation + ongoing world data. A 10-player world with several biomes can exceed 3 GB of save data alone. 8192 (8 GB) would give more comfortable headroom, especially since the platform likely provisions exactly this amount.
Password appears in the process argument list. -password "${SERVER_PASSWORD}" is visible via ps aux / /proc/<pid>/cmdline inside the container. This is inherent to Valheim's launcher (no config file), so it can't be fixed here, but it's worth a one-line note in the game description or README for security-conscious operators: "Note: the server password is visible in the container's process list because Valheim only accepts launch arguments."
defaultConfig.ServerName: GBRHosting - {SERVER_NAME} — this depends on the platform resolving the {SERVER_NAME} template token before passing it as an env var. If the runner passes it through literally, the game name would contain the string {SERVER_NAME}. This is likely handled correctly by the platform (consistent with other games in the repo), but worth a quick sanity-check in a staging deploy.
3. Tests
The CI boot test uses config: {} (all defaults: no password, crossplay off). The [ -n "${SERVER_PASSWORD}" ] and [ "${CROSSPLAY}" = "true" ] branches are therefore untested. A second test scenario (or a documented manual check) with Crossplay: true and a valid password would guard against regressions in the conditional-argument construction.
The readyExample in test.yaml correctly exercises the readyPattern, including the "sinze" typo. Good.
4. Overall assessment
The removal of MaxPlayers was the right call — Valheim's dedicated server binary has no such flag, and the previous version would have silently dropped the argument. The startup command is clean and correctly quotes all user-supplied values. The ready pattern is accurate, the install config matches the correct Steam app ID, and the test setup is sound.
The single item to resolve before merge is confirming the execution shell supports bash array syntax. Everything else is polish. Once that's verified, this is good to merge.
Automated review by AI Git Bot
## 🤖 AI Code Review
## 1. Blocking issues
**Bash array syntax — verify the execution shell.**
The `defaultStartupCommand` still relies on bash-specific array constructs:
```bash
args=(-name "..." -port 2456 ...); args+=(-password "..."); ./valheim_server.x86_64 "${args[@]}"
```
If the platform (or the cm2network/steamcmd image) invokes this command via `/bin/sh` (dash, busybox ash), the `args=(...)` assignment will produce a syntax error and the container will exit immediately. The boot test passing suggests this works in the CI environment, but please confirm:
- The image's `/bin/sh` symlink points to `bash`, **or**
- The platform's runner explicitly executes startup commands via `bash -c '…'`.
If neither is guaranteed, the command would need to be rewritten as a flat argument list (e.g., building a positional-parameter string, or using `eval`). This is a one-time check; if confirmed, no code change is needed.
## 2. Non-blocking suggestions
**Port 2457/udp — please confirm it's actually required.**
Most Valheim documentation (official guide, SteamDB, the lloesche and community-valheim-tools repos) lists only **2456/udp**. A small number of hosting wikis mention 2457 as a query/heartbeat port, but I couldn't find an authoritative source for it. If it's not needed, removing it reduces the exposed attack surface. If it *is* needed, a brief inline comment (`# query/heartbeat (source: …)`) would help future maintainers.
**`ServerPassword` schema could enforce `minLength: 5`.**
The description documents the 5-char minimum, but the schema doesn't reject a 3-char value. The server will crash-loop, and the user sees an opaque error. Suggested schema:
```yaml
ServerPassword:
...
anyOf:
- const: ""
- type: string
minLength: 5
```
**`requiredDiskMb: 4096` may be tight for larger worlds.**
~1 GB Steam download + world generation + ongoing world data. A 10-player world with several biomes can exceed 3 GB of save data alone. 8192 (8 GB) would give more comfortable headroom, especially since the platform likely provisions exactly this amount.
**Password appears in the process argument list.**
`-password "${SERVER_PASSWORD}"` is visible via `ps aux` / `/proc/<pid>/cmdline` inside the container. This is inherent to Valheim's launcher (no config file), so it can't be fixed here, but it's worth a one-line note in the game description or README for security-conscious operators: *"Note: the server password is visible in the container's process list because Valheim only accepts launch arguments."*
**`defaultConfig.ServerName: GBRHosting - {SERVER_NAME}`** — this depends on the platform resolving the `{SERVER_NAME}` template token before passing it as an env var. If the runner passes it through literally, the game name would contain the string `{SERVER_NAME}`. This is likely handled correctly by the platform (consistent with other games in the repo), but worth a quick sanity-check in a staging deploy.
## 3. Tests
- The CI boot test uses `config: {}` (all defaults: no password, crossplay off). The `[ -n "${SERVER_PASSWORD}" ]` and `[ "${CROSSPLAY}" = "true" ]` branches are therefore untested. A second test scenario (or a documented manual check) with `Crossplay: true` and a valid password would guard against regressions in the conditional-argument construction.
- The `readyExample` in `test.yaml` correctly exercises the `readyPattern`, including the "sinze" typo. Good.
## 4. Overall assessment
The removal of `MaxPlayers` was the right call — Valheim's dedicated server binary has no such flag, and the previous version would have silently dropped the argument. The startup command is clean and correctly quotes all user-supplied values. The ready pattern is accurate, the install config matches the correct Steam app ID, and the test setup is sound.
The single item to resolve before merge is confirming the execution shell supports bash array syntax. Everything else is polish. Once that's verified, this is good to merge.
---
*Automated review by AI Git Bot*
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Drafted by the GBR AI builder. Review before merging: check the settings, ports and descriptions against the game's documentation.
cm2network/steamcmd, Steam app 896660Checked for real
Notes from research: Crossplay is enabled with the -crossplay launch flag (allows Xbox, PS5, Switch 2, and Game Pass players to join; a join code is printed to the server log). BepInEx and ValheimPlus mods are supported via the lloesche and community-valheim-tools images. Server password must be at least 5 characters or valheim_server.x86_64 refuses to start. There is no config file; all settings are launch arguments. World data lives in a worlds/ subfolder under the -savedir path. Granting CAP_SYS_NICE is optional but avoids a thread-priority warning. The pfeiffermax image explicitly runs as a non-root user; lloesche and community-valheim-tools images also support non-root operation. First start downloads ~1 GB from Steam.
Sources
🤖 AI Code Review
1. Blocking issues
Bash array syntax in
defaultStartupCommandmay not work in all shells.The startup command uses bash-specific array syntax (
args=(...),args+=(...),"${args[@]}"). If the platform invokes this with/bin/sh(dash, busybox ash, etc.) rather than/bin/bash, the command will fail immediately. Please verify that the cm2network/steamcmd image's/bin/shis actually bash, or that the platform explicitly execs viabash -c. If it's dash, you'd need to rewrite as a simple positional-argument list or use a different construction.Config-to-env-var mapping for
CrossplayandMaxPlayersneeds verification.The schema keys are
CrossplayandMaxPlayers, but the startup command reads${CROSSPLAY}and${MAX_PLAYERS}. This implies the platform performs a PascalCase → SNAKE_CASE conversion (and boolean → lowercase string). This isn't obvious from the diff alone. Please confirm the platform'sconfigSchema→ environment variable naming convention actually producesCROSSPLAYandMAX_PLAYERSfrom those keys. A mismatch here would silently disable crossplay and max-players (the[ ... ]guards would just evaluate to false/empty), making the settings appear to work but have no effect.2. Non-blocking suggestions
ServerPassword schema is missing
minLengthenforcement.The description says "Must be at least 5 characters if set" and the notes confirm the binary refuses to start with shorter passwords, but the schema has no
minLength. A user who types a 3-char password will get a crash-loop with no UI-level hint. Consider:MaxPlayers has no bounds.
Add
minimum: 1andmaximum: 32(or whatever Valheim's hard cap is) so the UI can reject nonsensical values before the server tries to start.Port 2457/udp — please double-check.
Valheim's official and most community sources list only 2456/udp for the dedicated server. I couldn't find a reliable reference to 2457/udp being required. If it's not needed, an extra UDP port widens the attack surface for no benefit. If it is needed (e.g., for a query/discovery protocol), a short comment in the YAML would help future reviewers.
requiredDiskMb: 4096may be tight.The PR notes mention ~1 GB Steam download plus world data in
worlds/. A single world can grow several GB with biomes, builds, and thegenlocdata. 4 GB minimum leaves little headroom for a 10-player world. Consider 8192 (8 GB) unless the platform enforces separate volume sizing.Minor:
appIdis a quoted string"896660".This is correct if the schema requires a string, but worth a quick check that the
installConfig.appIdschema type matches (string vs integer) to avoid a validation failure in stricter parsers.3. Tests
test.yaml) exercises the default config (no password, no crossplay, default world name). Consider adding a second scenario or at least noting in the PR that crossplay enabled and password set paths were not CI-verified. The[ -n "${SERVER_PASSWORD}" ]and[ "${CROSSPLAY}" = "true" ]branches are untested by the harness as written.readyPatternis validated against thereadyExample, but a regression test that asserts the pattern does not match a partial/loading line (e.g., "Loading: 45%…") would guard against a future log-format change causing false readiness.4. Overall assessment
The configuration is well-researched, the ready pattern correctly accounts for Valheim's "sinze" typo, and the test setup is reasonable. The two items that need confirmation before merge are the shell compatibility of the bash array syntax and the config-key → env-var naming convention for
Crossplay/MaxPlayers— both are silent-failure risks that would only surface at runtime for end users. The schema validation gaps (password length, player bounds) are worth fixing but are UX polish rather than correctness bugs. Once those two verifications are confirmed, this is ready to merge.Automated review by AI Git Bot
🤖 AI Code Review
1. Blocking issues
Bash array syntax — verify the execution shell.
The
defaultStartupCommandstill relies on bash-specific array constructs:If the platform (or the cm2network/steamcmd image) invokes this command via
/bin/sh(dash, busybox ash), theargs=(...)assignment will produce a syntax error and the container will exit immediately. The boot test passing suggests this works in the CI environment, but please confirm:/bin/shsymlink points tobash, orbash -c '…'.If neither is guaranteed, the command would need to be rewritten as a flat argument list (e.g., building a positional-parameter string, or using
eval). This is a one-time check; if confirmed, no code change is needed.2. Non-blocking suggestions
Port 2457/udp — please confirm it's actually required.
Most Valheim documentation (official guide, SteamDB, the lloesche and community-valheim-tools repos) lists only 2456/udp. A small number of hosting wikis mention 2457 as a query/heartbeat port, but I couldn't find an authoritative source for it. If it's not needed, removing it reduces the exposed attack surface. If it is needed, a brief inline comment (
# query/heartbeat (source: …)) would help future maintainers.ServerPasswordschema could enforceminLength: 5.The description documents the 5-char minimum, but the schema doesn't reject a 3-char value. The server will crash-loop, and the user sees an opaque error. Suggested schema:
requiredDiskMb: 4096may be tight for larger worlds.~1 GB Steam download + world generation + ongoing world data. A 10-player world with several biomes can exceed 3 GB of save data alone. 8192 (8 GB) would give more comfortable headroom, especially since the platform likely provisions exactly this amount.
Password appears in the process argument list.
-password "${SERVER_PASSWORD}"is visible viaps aux//proc/<pid>/cmdlineinside the container. This is inherent to Valheim's launcher (no config file), so it can't be fixed here, but it's worth a one-line note in the game description or README for security-conscious operators: "Note: the server password is visible in the container's process list because Valheim only accepts launch arguments."defaultConfig.ServerName: GBRHosting - {SERVER_NAME}— this depends on the platform resolving the{SERVER_NAME}template token before passing it as an env var. If the runner passes it through literally, the game name would contain the string{SERVER_NAME}. This is likely handled correctly by the platform (consistent with other games in the repo), but worth a quick sanity-check in a staging deploy.3. Tests
config: {}(all defaults: no password, crossplay off). The[ -n "${SERVER_PASSWORD}" ]and[ "${CROSSPLAY}" = "true" ]branches are therefore untested. A second test scenario (or a documented manual check) withCrossplay: trueand a valid password would guard against regressions in the conditional-argument construction.readyExampleintest.yamlcorrectly exercises thereadyPattern, including the "sinze" typo. Good.4. Overall assessment
The removal of
MaxPlayerswas the right call — Valheim's dedicated server binary has no such flag, and the previous version would have silently dropped the argument. The startup command is clean and correctly quotes all user-supplied values. The ready pattern is accurate, the install config matches the correct Steam app ID, and the test setup is sound.The single item to resolve before merge is confirming the execution shell supports bash array syntax. Everything else is polish. Once that's verified, this is good to merge.
Automated review by AI Git Bot
greg referenced this pull request2026-10-25 21:47:38 +00:00
Pull request closed