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