From 936c8bb81c9e5070df9b5edafbffbb6682b5fa44 Mon Sep 17 00:00:00 2001 From: mwiegand Date: Sat, 9 May 2026 14:03:12 +0200 Subject: [PATCH] fix(deploy): ExecStart srcds_run from merged overlay, not installation/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit srcds_run is a shell script that cd's to its own dirname before exec'ing srcds_linux, so WorkingDirectory has no effect — the binary's path is what determines where the engine reads gameinfo.txt and addons from. Pointing at installation/srcds_run resolved everything against the lower layer, so overlay-provided Metamod/SourceMod plugins and cfgs (zonemod, confogl) never loaded. Switch to runtime/%i/merged/srcds_run so the engine sees the merged tree. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../usr/local/lib/systemd/system/left4me-server@.service | 8 +++++++- deploy/tests/test_deploy_artifacts.py | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/deploy/files/usr/local/lib/systemd/system/left4me-server@.service b/deploy/files/usr/local/lib/systemd/system/left4me-server@.service index d5d4698..e6f5d4f 100644 --- a/deploy/files/usr/local/lib/systemd/system/left4me-server@.service +++ b/deploy/files/usr/local/lib/systemd/system/left4me-server@.service @@ -33,7 +33,13 @@ WorkingDirectory=-/var/lib/left4me/runtime/%i/merged/left4dead2 # anyway. ExecStopPost (not ExecStop) so unmount runs after the cgroup is # cleared; ExecStop runs while srcds is still alive and would EBUSY. ExecStartPre=+/usr/local/libexec/left4me/left4me-overlay mount %i -ExecStart=/var/lib/left4me/installation/srcds_run -game left4dead2 +hostport ${L4D2_PORT} $L4D2_ARGS +# Run from the merged overlay, NOT installation/. srcds_run is a shell +# script that `cd`s to its own dirname before exec'ing srcds_linux, so the +# binary's path determines where the engine reads gameinfo.txt and addons +# from — WorkingDirectory has no effect. Invoking installation/srcds_run +# would resolve everything against the lower layer and never see overlay- +# provided plugins (Metamod/SourceMod) or cfgs (zonemod, confogl). +ExecStart=/var/lib/left4me/runtime/%i/merged/srcds_run -game left4dead2 +hostport ${L4D2_PORT} $L4D2_ARGS ExecStopPost=+/usr/local/libexec/left4me/left4me-overlay umount %i Restart=on-failure RestartSec=5 diff --git a/deploy/tests/test_deploy_artifacts.py b/deploy/tests/test_deploy_artifacts.py index d870893..09fe5ce 100644 --- a/deploy/tests/test_deploy_artifacts.py +++ b/deploy/tests/test_deploy_artifacts.py @@ -67,7 +67,11 @@ def test_server_unit_contains_required_runtime_contract(): # mount helper before the merged dir exists. ExecStart re-applies and # finds the dir once the mount has landed. assert "WorkingDirectory=-/var/lib/left4me/runtime/%i/merged/left4dead2" in unit - assert "ExecStart=/var/lib/left4me/installation/srcds_run" in unit + # ExecStart must invoke srcds_run from the *merged* overlay tree, not + # from installation/. srcds_run cds to its own dirname; if we point at + # installation/, the engine reads gameinfo.txt and addons from the lower + # layer and never sees overlay plugins (Metamod/SourceMod) or cfgs. + assert "ExecStart=/var/lib/left4me/runtime/%i/merged/srcds_run" in unit assert "$L4D2_ARGS" in unit assert "${L4D2_ARGS}" not in unit assert "NoNewPrivileges=true" in unit