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.
22 lines
1.4 KiB
Text
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
|