# left4me gameserver — system unit, one instance per gameserver. # # This is the REFERENCE COPY of the deployed unit base body. The live # source is the systemd/units reactor at # ~/Projekte/ckn-bw/bundles/left4me/metadata.py (look for # 'left4me-server@.service'). # # Hardening: see left4me-server@.service.d/10-hardening.conf # # Threat model: docs/superpowers/specs/2026-05-15-hardening-threat-model.md # Defenses survey: docs/superpowers/specs/2026-05-15-hardening-defenses-survey.md # Test plan + results: docs/superpowers/specs/2026-05-15-hardening-test-plan.md [Unit] Description=left4me server instance %i After=network-online.target Wants=network-online.target # Bound the restart loop. Without these, a persistent ExecStartPre or # ExecStart failure spins indefinitely. StartLimitBurst=5 StartLimitIntervalSec=60s [Service] Type=simple User=left4me Group=left4me EnvironmentFile=/etc/left4me/host.env EnvironmentFile=/var/lib/left4me/instances/%i/instance.env # `-` prefix: chdir failure is non-fatal. The merged dir only exists # once ExecStartPre's overlay mount succeeds. WorkingDirectory=-/var/lib/left4me/runtime/%i/merged/left4dead2 # `+` prefix runs the helper as PID 1 (root, all caps, host # namespaces) — required because the hardening drop-in sets # NoNewPrivileges and PrivateUsers; both block sudo's setuid path. # nsenter into PID 1's mount namespace ensures the umount in # ExecStopPost succeeds without EBUSY from the unit's own # slave-mount tree. ExecStartPre=+/usr/bin/nsenter --mount=/proc/1/ns/mnt -- /usr/local/libexec/left4me/left4me-overlay mount %i # Run from the merged overlay, NOT installation/. srcds_run cds to its # own dirname before exec'ing srcds_linux; the binary's path determines # gameinfo + addons lookup. ExecStart=/var/lib/left4me/runtime/%i/merged/srcds_run -game left4dead2 +hostport ${L4D2_PORT} $L4D2_ARGS ExecStopPost=+/usr/bin/nsenter --mount=/proc/1/ns/mnt -- /usr/local/libexec/left4me/left4me-overlay umount %i Restart=on-failure RestartSec=5 # === Resource control baseline === # See docs/superpowers/specs/2026-05-09-l4d2-server-host-perf-baseline-design.md Slice=l4d2-game.slice Nice=-5 IOSchedulingClass=best-effort IOSchedulingPriority=4 OOMScoreAdjust=-200 MemoryHigh=1.5G MemoryMax=2G TasksMax=256 LimitNOFILE=65536 KillSignal=SIGINT TimeoutStopSec=15s LogRateLimitIntervalSec=0 [Install] WantedBy=multi-user.target