fix: steamcmd install dir
Build and Publish Container / Publish Linux container (push) Successful in 4m3s

This commit is contained in:
2026-10-05 18:25:51 -04:00
parent c79aad1cb9
commit 516f1cfde2
7 changed files with 28 additions and 23 deletions
+4 -4
View File
@@ -7,10 +7,10 @@ RUN dpkg --add-architecture i386 \
ca-certificates curl lib32gcc-s1 python3 python3-pip python3-venv \
&& rm -rf /var/lib/apt/lists/* \
&& useradd --create-home --shell /bin/bash progression \
&& mkdir -p /opt/steamcmd/steamapps /srv/progression/.data \
&& mkdir -p /opt/steamcmd/steamapps /srv/progression/.data /srv/steam-library/steamapps \
&& curl -fsSL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz \
| tar -xz -C /opt/steamcmd \
&& chown -R progression:progression /opt/steamcmd /srv/progression
&& chown -R progression:progression /opt/steamcmd /srv/progression /srv/steam-library
WORKDIR /srv/progression
COPY --chown=progression:progression requirements-web.txt ./
@@ -26,12 +26,12 @@ ENV HOME=/root \
PROGRESSION_PORT=8000 \
PROGRESSION_DB_PATH=.data/progression.db \
STEAMCMD_PATH=/opt/steamcmd/steamcmd.sh \
STEAMCMD_WORKSHOP_DIR=/opt/steamcmd/steamapps/workshop/content/294100 \
STEAMCMD_WORKSHOP_DIR=/srv/steam-library/steamapps/workshop/content/294100 \
REFRESH_INTERVAL_SECONDS=3600 \
REFRESH_ON_STARTUP=true \
INITIAL_DOWNLOAD_TIMEOUT_SECONDS=43200
VOLUME ["/srv/progression/.data", "/opt/steamcmd/steamapps"]
VOLUME ["/srv/progression/.data", "/srv/steam-library/steamapps"]
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS http://127.0.0.1:8000/api/health || exit 1
+1 -1
View File
@@ -11,7 +11,7 @@ services:
INITIAL_DOWNLOAD_TIMEOUT_SECONDS: ${INITIAL_DOWNLOAD_TIMEOUT_SECONDS:-43200}
volumes:
- progression-data:/srv/progression/.data
- progression-workshop:/opt/steamcmd/steamapps
- progression-workshop:/srv/steam-library/steamapps
volumes:
progression-data:
+7 -5
View File
@@ -22,11 +22,13 @@ result, and completion percentage in Dockhand or with `docker compose logs -f`.
Failed batches also include SteamCMD's output tail so network, subscription, and
filesystem errors are visible directly in the container log.
SteamCMD is forced to use `/opt/steamcmd` so Workshop content always lands in
the mounted volume. On the first `I/O Operation Failed` result, transient `.acf`,
download, and temp state is moved into `.progression-recovery`; completed mod
directories are left untouched. Startup also checks that the volume has enough
free space for the remaining Steam metadata estimate.
SteamCMD is installed in `/opt/steamcmd`, while its forced library root is the
separate `/srv/steam-library` path. The existing `progression-workshop` volume
is mounted below that library root, so upgrades keep all completed downloads.
On the first `I/O Operation Failed` result, transient `.acf`, download, and temp
state is moved into `.progression-recovery`; completed mod directories are left
untouched. Startup also checks that the volume has enough free space for the
remaining Steam metadata estimate.
The image does not switch Unix users at startup because some rootless and
capability-restricted container hosts block `setuid`. The process remains inside
+2 -2
View File
@@ -18,7 +18,7 @@ services:
CONTENT_COLLECTION_URL: ${CONTENT_COLLECTION_URL:-https://steamcommunity.com/sharedfiles/filedetails/?id=3521319712}
COSMETICS_COLLECTION_URL: ${COSMETICS_COLLECTION_URL:-https://steamcommunity.com/sharedfiles/filedetails/?id=3637541646}
STEAMCMD_PATH: /opt/steamcmd/steamcmd.sh
STEAMCMD_WORKSHOP_DIR: /opt/steamcmd/steamapps/workshop/content/294100
STEAMCMD_WORKSHOP_DIR: /srv/steam-library/steamapps/workshop/content/294100
STEAMCMD_BATCH_SIZE: ${STEAMCMD_BATCH_SIZE:-25}
STEAMCMD_TIMEOUT_SECONDS: ${STEAMCMD_TIMEOUT_SECONDS:-1800}
REFRESH_INTERVAL_SECONDS: ${REFRESH_INTERVAL_SECONDS:-3600}
@@ -26,7 +26,7 @@ services:
INITIAL_DOWNLOAD_TIMEOUT_SECONDS: ${INITIAL_DOWNLOAD_TIMEOUT_SECONDS:-43200}
volumes:
- progression-data:/srv/progression/.data
- progression-workshop:/opt/steamcmd/steamapps
- progression-workshop:/srv/steam-library/steamapps
volumes:
progression-data:
+1 -1
View File
@@ -13,6 +13,6 @@ prepare_volume() {
}
prepare_volume /srv/progression/.data
prepare_volume /opt/steamcmd/steamapps
prepare_volume /srv/steam-library/steamapps
exec "$@"
+4 -7
View File
@@ -192,13 +192,10 @@ class SteamCmdRunner:
raise ValueError(f"Invalid Workshop ids: {', '.join(invalid)}")
self.ensure_workshop_writable()
command = [
executable,
"+force_install_dir",
str(self.install_root),
"+login",
"anonymous",
]
command = [executable]
if self.install_root.resolve() != Path(executable).resolve().parent:
command.extend(["+force_install_dir", str(self.install_root)])
command.extend(["+login", "anonymous"])
for workshop_id in workshop_ids:
command.extend(
[
+9 -3
View File
@@ -201,10 +201,16 @@ class BackendTests(unittest.TestCase):
def test_steamcmd_runner_forces_mounted_install_root(self, run: Mock) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
executable = root / "steamcmd"
executable = root / "steamcmd-bin" / "steamcmd"
executable.parent.mkdir()
executable.write_text("", encoding="utf-8")
content_dir = (
root / "steamapps" / "workshop" / "content" / "294100"
root
/ "steam-library"
/ "steamapps"
/ "workshop"
/ "content"
/ "294100"
)
run.return_value = Mock(returncode=0, stdout="", stderr="")
runner = SteamCmdRunner(str(executable), content_dir, 60)
@@ -217,7 +223,7 @@ class BackendTests(unittest.TestCase):
[
str(executable.resolve()),
"+force_install_dir",
str(root),
str(root / "steam-library"),
"+login",
"anonymous",
],