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