[Unit] Description=OpenFUT FIFA17 UTAS host (PRODUCTION) — client-facing, Core-dependent Documentation=file:///home/alex/OpenFUT/scripts/systemd/README.md # PRODUCTION TEMPLATE — NOT INSTALLED. Requires=openfut-netns.service After=openfut-netns.service Wants=openfut-core.service After=openfut-core.service # `Wants` on Core, deliberately NOT `Requires`/`BindsTo`/`PartOf` — measured on # staging: those propagate a Core stop into a host stop, and a later Core start # does NOT bring the host back, so a routine Core restart would leave the client # with no server at all. With `Wants` the host survives a Core outage, answers # 503 `core_unavailable` (never a Python fallback), and resumes serving the # moment Core returns with no supervisor intervention. Both halves were proven # on the staging units. # # `Requires` on the netns unit IS correct: without the namespace the host would # bind the wrong network entirely. # StartLimit* MUST live in [Unit]: systemd 252 silently IGNORES them in # [Service] (`systemd-analyze verify` flags it), which would have left the # crash-loop ceiling at the 10s/5 default instead of the intended 60s window. StartLimitIntervalSec=60 StartLimitBurst=5 [Service] Type=exec User=root NetworkNamespacePath=/run/netns/openfut EnvironmentFile=/etc/openfut/host.env # Admission gate. Ordering alone proves nothing about readiness (Type=exec only # proves the binary exec'd). Core binds its port only after migrations and the # content pack have loaded, so "port open" is a real readiness signal here. # Bounded and FAILING rather than blocking: a host that waits forever looks # healthy to the supervisor while serving nobody. ExecStartPre=/home/alex/OpenFUT/scripts/systemd/openfut-wait-tcp.sh 127.0.0.1 18080 30 ExecStart=/home/alex/openfut-migration/promote-contract-20260822-184409/artifacts/openfut-utas-host KillSignal=SIGTERM KillMode=mixed TimeoutStopSec=30 Restart=on-failure RestartSec=5s StandardOutput=journal StandardError=journal SyslogIdentifier=openfut-host [Install] WantedBy=multi-user.target