left4me/l4d2host
2026-05-05 23:47:06 +02:00
..
fs chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
templates chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
tests chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
__init__.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
cli.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
instances.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
logs.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
process.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
pyproject.toml chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
README.md chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
spec.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
status.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
steam_install.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
systemd_user.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00

l4d2-host-lib

Python host library and CLI for managing L4D2 instances.

CLI

l4d2ctl exposes exactly these commands in v1:

  • install
  • initialize <name> -f <spec.yaml>
  • start <name>
  • stop <name>
  • delete <name>

Subprocess failures are fail-fast. Raw stderr is written to stderr and the command exits with the same subprocess return code.

Runtime Paths

The host library uses hard-coded runtime paths under /opt/l4d2:

  • /opt/l4d2/installation
  • /opt/l4d2/overlays/<overlay>
  • /opt/l4d2/instances/<name>
  • /opt/l4d2/runtime/<name>/{upper,work,merged}

Host Prerequisites

The host library intentionally does not install or preflight runtime dependencies. The target host must provide them before running l4d2ctl.

Validated on Debian 13 during the ckn@10.0.4.128 smoke test:

  • Python 3.12+ with virtualenv/pip tooling for installing l4d2host.
  • steamcmd available on PATH and able to self-update as the runtime user.
  • 32-bit compatibility libraries for SteamCMD on amd64 Debian: libc6-i386, lib32gcc-s1, lib32stdc++6.
  • fuse-overlayfs and fusermount3 for per-instance overlay mounts.
  • systemctl --user and journalctl --user available for the runtime user.
  • User lingering enabled when services must survive SSH sessions: sudo loginctl enable-linger <user>.
  • /opt/l4d2 created and writable by the runtime user.

Example Debian setup:

sudo apt-get update
sudo apt-get install -y \
  python3 python3-venv python3-pip \
  curl ca-certificates tar gzip \
  fuse-overlayfs fuse3 \
  libc6-i386 lib32gcc-s1 lib32stdc++6

sudo mkdir -p /opt/steamcmd /opt/l4d2/{installation,overlays,instances,runtime}
sudo chown -R "$USER:$USER" /opt/steamcmd /opt/l4d2
sudo loginctl enable-linger "$USER"

SteamCMD should be installed so the runtime user can update it. If installing from Valve's tarball, avoid symlinking steamcmd.sh directly because it derives its install root from $0. Use a wrapper instead:

curl -fsSL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz -o /tmp/steamcmd_linux.tar.gz
tar -xzf /tmp/steamcmd_linux.tar.gz -C /opt/steamcmd
sudo tee /usr/local/bin/steamcmd >/dev/null <<'EOF'
#!/bin/sh
exec /opt/steamcmd/steamcmd.sh "$@"
EOF
sudo chmod 755 /usr/local/bin/steamcmd
chmod 755 /opt/steamcmd/steamcmd.sh /opt/steamcmd/linux32/steamcmd
steamcmd +quit

uv is optional deployment tooling. Debian 13 did not provide an uv package during the smoke test, so install it explicitly if you want to use it for faster virtualenv/dependency setup. l4d2ctl does not require uv at runtime.

Web App Read APIs

These read APIs are provided for web app integration:

  • get_instance_status(name)
  • stream_instance_logs(name, lines=200, follow=True)