Refuse to run the Linux setup as root

setup-linux.sh accepted being run as root and simply set SUDO="". That quietly
broke everything user-scoped: PM2 keeps its process list in $HOME/.pm2 and the
login entry goes in $HOME/.config/autostart, so under sudo both landed in /root.
The install reported success, then `pm2 list` as the real user showed nothing -
it was talking to a different daemon - and the autostart entry sat in a home
directory that never logs in.

Both scripts now refuse, and name the account to use when SUDO_USER says how
they were invoked. setup-linux.sh still uses sudo for apt, which is the only
part that needs it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-09-13 13:21:59 -05:00
co-authored by Claude Opus 5
parent a6a79bba7e
commit 153b1273c3
2 changed files with 23 additions and 5 deletions
+10
View File
@@ -31,6 +31,16 @@ done
info() { printf ' %s\n' "$1"; } info() { printf ' %s\n' "$1"; }
warn() { printf ' ! %s\n' "$1" >&2; } warn() { printf ' ! %s\n' "$1" >&2; }
# Same reason as setup-linux.sh: PM2's process list lives in $HOME/.pm2 and the
# login entry in $HOME/.config/autostart. As root both go to /root, invisible to
# the account that actually logs in.
if [ "$(id -u)" -eq 0 ]; then
echo " [X] do not run this as root${SUDO_USER:+ - run it as $SUDO_USER}." >&2
echo " PM2 and the login entry are per-user; as root they land in /root" >&2
echo " and your own 'pm2 list' will be empty." >&2
exit 1
fi
info "project root: $ROOT" info "project root: $ROOT"
# ── PM2 ───────────────────────────────────────────────────────────────────── # ── PM2 ─────────────────────────────────────────────────────────────────────
+13 -5
View File
@@ -29,12 +29,20 @@ echo
# ── sudo ──────────────────────────────────────────────────────────────────── # ── sudo ────────────────────────────────────────────────────────────────────
command -v apt-get >/dev/null 2>&1 || die "this script expects apt (Raspberry Pi OS, Debian, Ubuntu)" command -v apt-get >/dev/null 2>&1 || die "this script expects apt (Raspberry Pi OS, Debian, Ubuntu)"
SUDO="" # Must NOT run as root. Almost everything here is user-scoped: PM2 keeps its
if [ "$(id -u)" -ne 0 ]; then # process list in $HOME/.pm2, and the login entry goes in $HOME/.config/autostart.
command -v sudo >/dev/null 2>&1 || die "not root and sudo is not installed" # Run under sudo and both land in /root - PM2 starts a daemon your own account
SUDO="sudo" # cannot see, and the autostart entry sits in a home directory that never logs
info "some steps need sudo; you may be prompted" # in. It looks like it worked, then `pm2 list` is empty.
if [ "$(id -u)" -eq 0 ]; then
if [ -n "${SUDO_USER:-}" ]; then
die "do not run this with sudo - run it as $SUDO_USER; it will ask for sudo only where it needs it"
fi
die "do not run this as root - run it as the user that will own the instance"
fi fi
command -v sudo >/dev/null 2>&1 || die "sudo is required (for apt) and is not installed"
SUDO="sudo"
info "apt steps need sudo; you may be prompted"
# ── system packages ───────────────────────────────────────────────────────── # ── system packages ─────────────────────────────────────────────────────────
# xdotool raises the browser window (pygetwindow has no X11 backend, so the # xdotool raises the browser window (pygetwindow has no X11 backend, so the