From 5346033e504cf0839bf947acb21ae3fa293dcefa Mon Sep 17 00:00:00 2001 From: Anastassios Nanos Date: Sat, 31 Oct 2026 17:18:06 +0200 Subject: [PATCH] fix(install): Make the rootless refusal usable from curl | sh A user on a fresh Ubuntu 26.04 ran `curl -fsSL brig.sh/install | sh` and got the rootless refusal. Three parts of it did not hold for them: - "Nothing was downloaded" was not true. brig's installer had already fetched cosign (about 130 MB), the brig archive and this script. The message now says that the installer stopped before it downloaded the bundle. - "See docs/rootless.md" pointed at a checkout the user does not have. The refusal, the install summary and --help now give the guide's URL. - "run this installer again" named a script the user never ran. INSTALL_BRIG_RERUN lets the caller say how to run the install again, and the refusal prints that command after the root commands. Without it the message is unchanged. The modules-load.d comment named brig-rootless-setup.sh, which this installer's root commands do not run. Both copies now say "brig's rootless setup". Signed-off-by: Anastassios Nanos --- docs/rootless.md | 5 +++-- install.sh | 32 ++++++++++++++++++++++---------- scripts/build-bundle.sh | 4 ++-- tests/install-preflight.sh | 20 +++++++++++++++++--- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/docs/rootless.md b/docs/rootless.md index 0393e83..06a42c3 100644 --- a/docs/rootless.md +++ b/docs/rootless.md @@ -184,8 +184,9 @@ $ curl -fsSL https://raw.githubusercontent.com/NOFireAI/brig-standalone-linux/ma no access to /dev/kvm from inside the user namespace no access to /dev/vhost-vsock from inside the user namespace - Nothing was downloaded: sudo cannot run here without a password. - Run the commands below as root, or ask an admin to, and then run this + The installer stopped before it downloaded the bundle: sudo cannot run here + without a password. + Run the commands below as root, or ask an admin to, and then run the installer again. It needs no sudo after that. sudo sh -eu <<'BRIG_ROOT' diff --git a/install.sh b/install.sh index 99ae0ce..1b52192 100755 --- a/install.sh +++ b/install.sh @@ -81,6 +81,10 @@ NAMESPACE="brig" SIG_IDENTITY_REGEXP="${INSTALL_BRIG_SIG_IDENTITY:-^https://github.com/NOFireAI/brig-standalone-linux/.github/workflows/release.yml@refs/tags/}" SIG_OIDC_ISSUER="${INSTALL_BRIG_SIG_ISSUER:-https://token.actions.githubusercontent.com}" +# Messages name the rootless guide by URL: an install piped from curl has no +# checkout to find docs/rootless.md in. +ROOTLESS_DOC="https://github.com/NOFireAI/brig-standalone-linux/blob/main/docs/rootless.md" + # ---------------------------------------------------------------- logging # say() prints a stage detail, only in verbose mode. warn()/fatal() always print, @@ -128,8 +132,9 @@ Usage: install.sh [--help] [--verbose] [--quiet] [--system|--user] Fetches the brig release tarball and installs it. As root the tree goes to /var/lib/brig/data with state in /var/lib/brig and the socket in /run/brig. As a normal user it goes to ~/.local/share/brig instead and nothing outside $HOME is -touched, which needs the host prepared once: see docs/rootless.md. It builds -nothing. +touched, which needs the host prepared once: see the rootless guide at +https://github.com/NOFireAI/brig-standalone-linux/blob/main/docs/rootless.md. +It builds nothing. INSTALL_BRIG_RELEASE_REPO repo that publishes the tarball (default: NOFireAI/brig-standalone-linux) @@ -157,6 +162,8 @@ nothing. CONTAINERD_SNAPSHOTTER=devmapper to switch at runtime) INSTALL_BRIG_POOL_SIZE thin pool data size (default: 100G, sparse) INSTALL_BRIG_POOL_PREALLOC true to fallocate the pool backing files + INSTALL_BRIG_RERUN the command to print for running the install again + once the host is prepared (default: none) INSTALL_BRIG_DEBUG true for set -x USAGE } @@ -448,8 +455,8 @@ FIX need="$need\n vhost_vsock is not loaded at boot" cat >> "$fix" <<'FIX' cat > /etc/modules-load.d/brig.conf <<'CONF' -# brig: the vsock device the monitor gives the guest. Written by -# brig-rootless-setup.sh; the matching udev rule grants access to it. +# brig: the vsock device the monitor gives the guest. Written by brig's +# rootless setup; the matching udev rule grants access to it. vhost_vsock CONF FIX @@ -507,8 +514,8 @@ FIX why="sudo cannot run here without a password" fi cat >&2 <&2 + fi if [ -z "${OWN_MADE:-}" ]; then - echo " With sudo of your own, run 'sudo -v' and then this installer again: it" >&2 + echo " With sudo of your own, run 'sudo -v' and then the installer again: it" >&2 echo " makes these itself." >&2 fi fi - echo " See docs/rootless.md." >&2 + echo " See $ROOTLESS_DOC" >&2 exit 1 } @@ -1122,13 +1134,13 @@ main() { if getent group "$BRIG_GROUP" >/dev/null 2>&1; then if [ "$BUNDLE_ROOTLESS" = "true" ]; then grp_note=" group: $BRIG_GROUP owns the socket, which is not enough to run - brig as a normal user: see docs/rootless.md, or run + brig as a normal user: see $ROOTLESS_DOC, or run $BIN_DIR/brig-ctl rootless as that user " else grp_note=" group: $BRIG_GROUP owns the socket, which is not enough to run brig as a normal user, and this bundle carries no rootless - path. Install a -rootless bundle for that: docs/rootless.md + path. Install a -rootless bundle for that: $ROOTLESS_DOC " fi fi diff --git a/scripts/build-bundle.sh b/scripts/build-bundle.sh index d25eedb..627d3d1 100755 --- a/scripts/build-bundle.sh +++ b/scripts/build-bundle.sh @@ -540,8 +540,8 @@ done # lists the module will do, so a re-run, or a host an admin prepared with a # file of their own, needs no sudo here. MODULES_FILE=/etc/modules-load.d/brig.conf -MODULES_WANT="# brig: the vsock device the monitor gives the guest. Written by -# brig-rootless-setup.sh; the matching udev rule grants access to it. +MODULES_WANT="# brig: the vsock device the monitor gives the guest. Written by brig's +# rootless setup; the matching udev rule grants access to it. vhost_vsock" if [ -d /sys/module/vhost_vsock ] && ! grep -qsx 'vhost_vsock' /etc/modules-load.d/*.conf /etc/modules; then diff --git a/tests/install-preflight.sh b/tests/install-preflight.sh index 2f06426..91496b3 100755 --- a/tests/install-preflight.sh +++ b/tests/install-preflight.sh @@ -87,12 +87,13 @@ for b in newuidmap setfacl iptables systemctl; do done chmod 0755 "$T/stub"/* +# run_install [VAR=value ...] runs install.sh with these set as well. run_install() { : > "$T/sudo.log" set +e env -u XDG_CONFIG_HOME -u XDG_DATA_HOME \ HOME="$T/home" XDG_RUNTIME_DIR="$T/run" PATH="$T/stub:$PATH" \ - INSTALL_BRIG_BUNDLE="$T/no-such-bundle.tar.gz" INSTALL_BRIG_TTY="$T/tty" \ + INSTALL_BRIG_BUNDLE="$T/no-such-bundle.tar.gz" INSTALL_BRIG_TTY="$T/tty" "$@" \ sh "$here/install.sh" > "$T/out.log" 2>&1 rc=$? set -e @@ -110,7 +111,11 @@ if grep -q "no-such-bundle" "$T/out.log"; then fail "the install went on to fetch the bundle" fi [ ! -e "$T/home/.local/share/brig" ] || fail "the install wrote $T/home/.local/share/brig" -grep -q "Nothing was downloaded" "$T/out.log" || { cat "$T/out.log" >&2; fail "no reason given"; } +grep -q "stopped before it downloaded the bundle" "$T/out.log" || { cat "$T/out.log" >&2; fail "no reason given"; } +grep -qF "See https://github.com/NOFireAI/brig-standalone-linux/blob/main/docs/rootless.md" "$T/out.log" \ + || { cat "$T/out.log" >&2; fail "the guide is not named by URL"; } +! grep -q "command to run again" "$T/out.log" \ + || { cat "$T/out.log" >&2; fail "a command to run again was printed without INSTALL_BRIG_RERUN"; } awk '/^sudo sh -eu <<.BRIG_ROOT.$/ {f=1; next} /^BRIG_ROOT$/ {f=0} f' "$T/out.log" > "$T/root.sh" [ -s "$T/root.sh" ] || { cat "$T/out.log" >&2; fail "no root commands printed"; } sh -n "$T/root.sh" || fail "the root commands are not valid sh" @@ -127,6 +132,15 @@ if [ -e /dev/kvm ]; then fi ok "without sudo the install stops before the download and prints the root commands" +# 1b. A caller that names how to run it again gets that command printed after +# the root commands. +run_install INSTALL_BRIG_RERUN="curl -fsSL https://brig.sh/install | sh" +[ "$rc" -ne 0 ] || fail "the install succeeded on a host that is not prepared" +awk '/^BRIG_ROOT$/ {f=1; next} f' "$T/out.log" \ + | grep -qxF " curl -fsSL https://brig.sh/install | sh" \ + || { cat "$T/out.log" >&2; fail "INSTALL_BRIG_RERUN was not printed after the root commands"; } +ok "the caller's command to run again is printed" + # 2. Not prepared, and sudo runs without a password: go on, and leave the # host settings to the rootless setup. touch "$T/sudo-ok" @@ -189,7 +203,7 @@ else rm -f "$T/stub/newuidmap" "$T/stub/setfacl" "$T/sudo-ok" "$T/tty" run_install if grep -q '^-v$' "$T/sudo.log"; then fail "sudo was asked for a password with no terminal"; fi - grep -q "Nothing was downloaded" "$T/out.log" || { cat "$T/out.log" >&2; fail "no stop without a terminal"; } + grep -q "stopped before it downloaded the bundle" "$T/out.log" || { cat "$T/out.log" >&2; fail "no stop without a terminal"; } : > "$T/tty" rm -f "$T/in-sudo" run_install