Windows: --install-service creates %ProgramFiles%\gpu-turnstile and
%ProgramData%\gpu-turnstile, copies the exe and (if absent) the env
file in, and registers the copy. Linux: binary goes to
/var/lib/gpu-turnstile (not /usr/local/sbin: replacing a running binary
needs directory write, which must not be granted on a shared system dir
to a sandboxed service). --no-copy registers the current location
as-is on both platforms.
The Linux install now mirrors the Windows virtual-account hardening: the
unit runs with DynamicUser=yes (transient per-service UID, no login),
ProtectSystem=strict with only StateDirectory writable (the install dir,
so self-update can rewrite the binary), NoNewPrivileges, empty
capability sets, restricted address families and a @system-service
syscall filter. Install copies the binary to /var/lib/gpu-turnstile and
the config to /etc/gpu-turnstile.env; Remove cleans up the unit and
binary but keeps the config.
The service package now has a Linux implementation alongside the Windows
one: systemd unit install/remove (/etc/systemd/system), readiness
notification (READY=1 via go-systemd) sent only after the listeners are
bound, a 30s watchdog, and STOPPING on shutdown. Listeners are pre-bound
so port conflicts fail fast and the readiness signal is truthful. The
notify calls are no-ops without NOTIFY_SOCKET (containers, shells) and
on non-Linux builds. --install-service/--remove-service work on both
platforms; the 'service install|remove' subcommand remains as an alias.