From 1968684c03acc2137b70464408514b9c0776da75 Mon Sep 17 00:00:00 2001 From: mwiegand Date: Thu, 7 May 2026 02:01:24 +0200 Subject: [PATCH] fix(deploy): MountFlags=shared on web service for fuse mount propagation ProtectSystem=full + ReadWritePaths implicitly give the unit a private mount namespace (systemd needs to remount /usr read-only). The default namespace propagation is slave, so mounts the worker creates inside never reach the host. The gameserver units (started via systemctl, each with their own namespace) then inherit a host that lacks the overlay, and their CHDIR into /var/lib/left4me/runtime//merged fails. Set MountFlags=shared so mount events propagate from the worker's namespace back to the host, then onward to gameserver units at their unshare time. Verified on test box: nsenter -t -m mount showed the fuse-overlayfs mount inside the worker but plain mount on the host did not, while web unit had ProtectSystem=full + ReadWritePaths. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../local/lib/systemd/system/left4me-web.service | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/deploy/files/usr/local/lib/systemd/system/left4me-web.service b/deploy/files/usr/local/lib/systemd/system/left4me-web.service index c6d6477..3465516 100644 --- a/deploy/files/usr/local/lib/systemd/system/left4me-web.service +++ b/deploy/files/usr/local/lib/systemd/system/left4me-web.service @@ -17,14 +17,15 @@ Restart=on-failure RestartSec=3 # NoNewPrivileges intentionally not set: the worker invokes fusermount3 # (setuid-root) and sudo to run the systemctl wrapper. -# PrivateTmp intentionally not set: it creates a private mount -# namespace, which would hide per-instance fuse-overlayfs mounts from -# the host and the gameserver units. The mount must land in the host -# namespace so the systemd-managed gameserver service inherits it at -# unshare time. Remaining hardening: dedicated user, ProtectSystem, -# ReadWritePaths, narrow sudoers allowlist. +# ProtectSystem=full + ReadWritePaths implicitly give this unit a +# private mount namespace. MountFlags=shared makes its mount events +# propagate back to the host so per-instance fuse-overlayfs mounts are +# visible to the gameserver units (which inherit host mounts at their +# own unshare time). Without it, the per-instance mount only exists +# inside the worker's namespace and the gameserver units fail CHDIR. ProtectSystem=full ReadWritePaths=/var/lib/left4me +MountFlags=shared [Install] WantedBy=multi-user.target