# sudoers.d/ci-web — NOPASSWD grant for the ci-web dashboard's service panel (Stage D). # # Installed to /etc/sudoers.d/ci-web, mode 0440, owner root:root, by # setup-web-linux.sh (which validates it with `visudo -cf` before/after # installing and rolls back on any failure -- see that script's step and # docs/WEB-UI.md's "Service management" section). # # SECURITY MODEL: # * Exact-command NOPASSWD only -- every line below is a literal, fully # qualified command with a literal unit name. No wildcards (`*`), no # bare `systemctl` entry, no `ALL` in the command position. This is the # entire reason ci-web (running as ci-runner, an unprivileged service # account) can safely be granted passwordless sudo for exactly these # nine command lines and nothing else -- ci-runner can never pass an # arbitrary unit name or subcommand through sudo, even if the web app # itself were compromised (defense in depth alongside the operations/ # services.py allow-list, which is the primary gate). # * ci-web.service deliberately has NO `stop` entry here -- matching # ManagedService("ci-web", ..., allow_stop=False) in # operations/services.py. Stopping the service that renders this very # sudoers-governed panel would lock the operator out with no way to # start it again from the UI. # * ci-web.service's "restart" is instead a *deferred* restart via # `systemd-run --on-active=2 systemctl restart ci-web.service` -- a # direct `systemctl restart ci-web.service` run from inside ci-web's # own worker process would kill the HTTP response before it could be # sent. The systemd-run invocation itself returns almost immediately # (it only *schedules* the restart 2s out), so the confirming request # completes normally. # # Before installing on a new host, verify the absolute paths below still # match this host's actual binaries: # command -v systemctl systemd-run # and edit both this file and Cmnd_Alias below if either is not under # /usr/bin (e.g. a distro that ships them under /bin or /usr/local/bin). # Confirmed /usr/bin/systemctl and /usr/bin/systemd-run on this host. Cmnd_Alias CI_WEB_SVC = \ /usr/bin/systemctl start act-runner.service, /usr/bin/systemctl stop act-runner.service, /usr/bin/systemctl restart act-runner.service, \ /usr/bin/systemctl start act-runner-rust.service, /usr/bin/systemctl stop act-runner-rust.service, /usr/bin/systemctl restart act-runner-rust.service, \ /usr/bin/systemctl start vmware-host.service, /usr/bin/systemctl stop vmware-host.service, /usr/bin/systemctl restart vmware-host.service, \ /usr/bin/systemd-run --on-active=2 systemctl restart ci-web.service ci-runner ALL=(root) NOPASSWD: CI_WEB_SVC