#!/bin/sh # lchat-svc — scoped systemctl for operators, without a root shell. # # Ubuntu 26.04 ships sudo-rs, which (unlike classic sudo) rejects argument # wildcards in sudoers — so `systemctl restart lchat-*` cannot be granted # directly. Operators go through this helper instead; sudoers grants only # `/usr/local/sbin/lchat-svc *` (a whole-argument wildcard, which sudo-rs # does allow), and the helper confines systemctl to lchat* units. Same shape # as lchat-env-install: the narrow, auditable privileged surface. Amend via a # reviewed PR + redeploy, never by hand on a box. # # lchat-svc daemon-reload # lchat-svc [--now] # verb ∈ start|stop|restart|reload|enable|disable|status|reset-failed|is-active|is-enabled set -eu verb="${1:-}" [ -n "$verb" ] || { echo "usage: lchat-svc [--now] | lchat-svc daemon-reload" >&2; exit 1; } # daemon-reload is unit-less and always safe to allow. if [ "$verb" = daemon-reload ]; then [ "$#" -eq 1 ] || { echo "daemon-reload takes no arguments" >&2; exit 1; } exec systemctl daemon-reload fi case "$verb" in start|stop|restart|reload|enable|disable|status|reset-failed|is-active|is-enabled) ;; *) echo "verb not permitted: $verb" >&2; exit 1 ;; esac shift # --now may follow enable/disable; pass it through if present. now="" if [ "${1:-}" = "--now" ]; then now="--now"; shift; fi [ "$#" -ge 1 ] || { echo "no unit given" >&2; exit 1; } for u in "$@"; do case "$u" in lchat|lchat-*|lchat@*|lchat.*) ;; *) echo "unit not permitted (lchat* only): $u" >&2; exit 1 ;; esac done exec systemctl "$verb" ${now:+"$now"} "$@"