flybrain/infra/config/fly-sudoers
acamilo 63ecc32b2f loop recovery: an escalation ladder that unsticks a trap on its own
Restart flysim, then reset to the current rung's milestone, then to the
archive below the best rung (never lower), one step per confirmed trap
that outlives the previous one. Two resets a day, three-hour restarts
once they are spent; the ladder starts over at a new best rung or after
six quiet hours. State and history live in the unit's StateDirectory so
a reboot does not forget where the ladder stood.

A router model list confirms each step; a 'not stuck' answer delays it
at most three probes and no answer leaves the watchdog to decide alone.
Each step is announced 60 s ahead in /run/fly/wd/recovery-notice.json
for the stage's recovery splash.

fly-loop-reset is the one new root surface (a sudoers line); 05-deploy
now converges config/fly-sudoers so a release can add it.
2026-09-28 21:23:33 +00:00

22 lines
1.4 KiB
Text

# infra/config/fly-sudoers — pushed to /etc/sudoers.d/fly-watchdog, mode
# 0440, validated with `visudo -c -f` before install.
#
# fly-watchdog.service runs as User=fly (docs/design/infra.md section 3:
# "all app units User=fly"), but its remediation is `systemctl restart
# <unit>` and, on the 5-consecutive-failure escalation, a container
# reboot. This is the minimum NOPASSWD surface for exactly what
# bin/fly-watchdog's checks actually restart (flysim, flystage, flycast,
# mediamtx, flypush), plus reboot. No `systemctl stop`, no
# `enable`/`disable`, no arbitrary unit name, and no units this script
# does not itself restart (xvfb, pulse, flystage-web are never touched by
# fly-watchdog's checks, so they are not granted here).
fly ALL=(root) NOPASSWD: /usr/bin/systemctl restart flysim.service
fly ALL=(root) NOPASSWD: /usr/bin/systemctl restart flystage.service
fly ALL=(root) NOPASSWD: /usr/bin/systemctl restart flycast.service
fly ALL=(root) NOPASSWD: /usr/bin/systemctl restart mediamtx.service
fly ALL=(root) NOPASSWD: /usr/bin/systemctl restart flypush.service
fly ALL=(root) NOPASSWD: /usr/sbin/reboot
# fly-loop-recover.service (also User=fly): its ladder restarts flysim (granted above) and
# resets to a milestone archive through this one root wrapper, which validates the rung,
# stops/resets/starts flysim and nothing else (infra/docs/loop-recovery.md).
fly ALL=(root) NOPASSWD: /opt/fly/bin/fly-loop-reset