left4me/deploy/files/usr/local/lib/systemd/system/left4me-web.service
mwiegand 38548ab0d7
chore(deploy): raise gunicorn thread pool to 32 for SSE headroom
Each SSE log-viewer or job-log stream holds a thread for its full
lifetime. With --threads 8, a handful of open browser tabs could
exhaust the pool. 32 keeps the same single-process scheduler invariant
(_claim_lock in job_worker is process-local) while giving SSE plenty
of headroom on the test box's user count.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 11:19:03 +02:00

31 lines
1.2 KiB
Desktop File

[Unit]
Description=left4me web application
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=left4me
Group=left4me
WorkingDirectory=/opt/left4me
Environment=HOME=/var/lib/left4me
Environment=PATH=/opt/left4me/.venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
EnvironmentFile=/etc/left4me/host.env
EnvironmentFile=/etc/left4me/web.env
ExecStart=/opt/left4me/.venv/bin/gunicorn --workers 1 --threads 32 --bind 0.0.0.0:8000 'l4d2web.app:create_app()'
Restart=on-failure
RestartSec=3
# NoNewPrivileges intentionally not set: the worker invokes fusermount3
# (setuid-root) and sudo to run the systemctl wrapper.
# 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