From 055c8fcf8f6dc8fedc234de1710d5261bb12797a Mon Sep 17 00:00:00 2001 From: boxswapper Date: Thu, 17 Sep 2026 11:40:31 -0600 Subject: [PATCH] roles/7dtd/tasks/main.yml: add lgsm dir + template tasks + bind mount for config-lgsm - deploys config each run --- roles/7dtd/tasks/main.yml | 20 ++++++++++++++++++++ roles/7dtd/templates/sdtdserver.cfg.j2 | 14 ++++++++++++++ vars.yml | 8 ++++++++ 3 files changed, 42 insertions(+) create mode 100644 roles/7dtd/templates/sdtdserver.cfg.j2 diff --git a/roles/7dtd/tasks/main.yml b/roles/7dtd/tasks/main.yml index 3491e92..23ef93c 100644 --- a/roles/7dtd/tasks/main.yml +++ b/roles/7dtd/tasks/main.yml @@ -41,6 +41,25 @@ group: '1000' mode: '0644' +# LinuxGSM reads config-lgsm/sdtdserver/sdtdserver.cfg on EVERY invocation (start/monitor/stop). +# Bind-mounting it makes the role the owner of that config (see vars.yml sdtd_lgsm_querymode); +# a previously unmanaged podman volume left defaults in place, causing the monitor crash-loop. +- name: Create 7 Days to Die LGSM config directory (container user) + ansible.builtin.file: + path: /opt/apps/7dtd/lgsm + state: directory + owner: '1000' + group: '1000' + mode: '0755' + +- name: Template 7 Days to Die LGSM config from vars.yml + ansible.builtin.template: + src: sdtdserver.cfg.j2 + dest: /opt/apps/7dtd/lgsm/sdtdserver.cfg + owner: '1000' + group: '1000' + mode: '0644' + - name: Deploy 7 Days to Die Server containers.podman.podman_container: image: "{{ sdtd_image }}" @@ -52,6 +71,7 @@ volumes: - /opt/apps/7dtd/data:/home/sdtdserver/.local/share/7DaysToDie:z - /opt/apps/7dtd/serverfiles:/home/sdtdserver/serverfiles:z + - /opt/apps/7dtd/lgsm:/home/sdtdserver/lgsm/config-lgsm/sdtdserver:z ports: # Required: game port (TCP+UDP), Steam query/beacon ports (UDP) - "26900:26900/tcp" diff --git a/roles/7dtd/templates/sdtdserver.cfg.j2 b/roles/7dtd/templates/sdtdserver.cfg.j2 new file mode 100644 index 0000000..c990db7 --- /dev/null +++ b/roles/7dtd/templates/sdtdserver.cfg.j2 @@ -0,0 +1,14 @@ +################################## +####### Instance Settings ######## +################################## +# Managed by Ansible (roles/7dtd/templates/sdtdserver.cfg.j2) - local edits are overwritten on re-run. +# Source of truth: sdtd_* variables in vars.yml. + +## 7dtd answers NO A2S query on the game port (ServerVisibility=0 + SteamNetworking disabled), +## so the default gamedig-based monitor (querymode=2) always fails and force-restarts the healthy +## server every ~5 min. querymode=1 checks the tmux session instead. +querymode="{{ sdtd_lgsm_querymode }}" + +## LGSM graceful stop reads ${telnetpassword} from this cfg (the game XML TelnetPassword is parsed +## into ${telnetpass}, a different var). Without it, stop falls back to a hard tmux kill. +telnetpassword="{{ sdtd_telnet_password }}" \ No newline at end of file diff --git a/vars.yml b/vars.yml index 9029c18..f375ff2 100755 --- a/vars.yml +++ b/vars.yml @@ -149,6 +149,14 @@ sdtd_pgid: 1000 sdtd_timezone: America/Denver sdtd_backup: "NO" sdtd_monitor: "YES" +## LinuxGSM config overrides (roles/7dtd/templates/sdtdserver.cfg.j2): +## - querymode=1: this server answers NO A2S query on 26900 (ServerVisibility=0 + SteamNetworking +## disabled), so the default gamedig-based monitor (querymode=2) always fails its query and +## force-restarts the HEALTHY server every ~5 min. Session-only check avoids that loop. +## - telnetpassword mirrors sdtd_telnet_password because LGSM's graceful stop reads +## ${telnetpassword} from its OWN cfg; the XML value is parsed into ${telnetpass} (different +## var) so without this the stop falls back to a hard tmux kill. Keep in sync below. +sdtd_lgsm_querymode: "1" ## CHANGE THESE before first deploy — the server is public and both passwords gate real access: ## sdtd_server_password is the join password players must enter; if it is empty the server has NO ## join password. sdtd_telnet_password guards the 8081/tcp admin console; if empty telnet only