Skip to content

fix(install): Stop before the download when sudo needs a password - #7

Merged
ananos merged 1 commit into
mainfrom
fix/install-stop-without-sudo
Sep 25, 2026
Merged

ananos merged 1 commit into
mainfrom
fix/install-stop-without-sudo

Conversation

@ananos

@ananos ananos commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Stacked on #6: the commands this prints write the per-user rule file that #6
introduces, and the setup reads the grant back from the devices the way #6
does. Review #6 first. Once it merges, this retargets to main.

Summary

For a user install on a host that is not prepared, install.sh printed the
missing host settings as a warning and went on. It downloaded and unpacked the
bundle, about 488 MB, and only then did brig-rootless-setup.sh ask for sudo. A
user without sudo was left at [sudo] password for <user>: with a half-done
install, or, without a terminal, with a failed one. brig's install guide says
the user path "asks for sudo at no point".

Now, when something needs root and sudo -n true fails, the installer stops
before the download. It prints what is missing, and one block of root commands
for this user and this prefix. An admin runs that block once, and the next run
of the installer needs no sudo at all. With sudo that runs without a password,
nothing changes: the setup makes the settings at the end, as before.

Changes

  • The preflight covers every sudo call the setup can make: the device grant,
    loading kvm and vhost_vsock, loading vhost_vsock at boot, the AppArmor
    profile for this prefix's rootlesskit, and home directories an earlier sudo
    run left root-owned.
  • The block is one sudo sh -eu <<'BRIG_ROOT' heredoc with the udev rule, the
    AppArmor profile and whatever else is missing, in dependency order. Its udev
    rule is the setup's own text, so the file an admin writes and the file the
    setup writes are identical (same sha256 on the live host below).
  • Missing uidmap or acl, or a missing subuid range, stop the install as
    before, since the setup never made them. The block now covers those too. The
    subuid range it offers starts past every range already in /etc/subuid and
    /etc/subgid, so it cannot overlap another user's.
  • A user with a sudo password is told to run sudo -v and then the installer
    again, which makes these itself.
  • The setup no longer asks sudo to load a module the kernel does not have,
    which was a password prompt for nothing.
  • docs/rootless.md shows the stop and the block.
  • tests/install-preflight.sh.

Testing

tests/install-preflight.sh runs install.sh as a user install against a stub
sudo, getfacl, stat, sysctl and modinfo, pointed at a bundle that does
not exist. A run that gets past the preflight fails on the fetch and says so.

$ sh tests/install-preflight.sh
ok - without sudo the install stops before the download and prints the root commands
ok - with sudo the install goes on to the download
ok - a prepared host needs no sudo

The same test against the previous install.sh:

$ sh tests/install-preflight.sh
[brig-install] WARNING: 3 host settings are still missing:
  no access to /dev/kvm from inside the user namespace
  no access to /dev/vhost-vsock from inside the user namespace
  no AppArmor profile for /tmp/tmp.p2LtlnPwoW/home/.local/share/brig/data/bin/rootlesskit
[brig-install] WARNING: brig-rootless-setup.sh will ask for sudo once to set those up
[brig-install] ERROR: tarball '/tmp/tmp.p2LtlnPwoW/no-such-bundle.tar.gz' not found
FAIL: the install went on to fetch the bundle

sh -n (dash) and shellcheck -s sh pass over install.sh,
build-bundle.sh, the three generated scripts and both tests.

Live, on an Ubuntu 24.04 host

A fresh user, brigtest2, with a subuid range and no sudo
(sudo -n true says "a password is required"), installed from a local copy of
the v0.1.0-rc8 rootless bundle. For the branch run, the bundle's setup and
brig-ctl were regenerated from these branches, and sysctl was stubbed to
report the AppArmor restriction so the profile shows up in the block. This host
does not set it.

The previous installer, on the release bundle, unpacked and then failed:

  devices    granting brigtest2 access to kvm vhost-vsock (needs sudo)
sudo: a terminal is required to read the password; ...
[brig-install] ERROR: the rootless setup failed
--- left behind in $HOME
488M	/home/brigtest2/.local/share/brig

This branch stopped before anything was unpacked:

[brig-install] ERROR: this host is not set up for a rootless brig:
  no AppArmor profile for /home/brigtest2/.local/share/brig/data/bin/rootlesskit
  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
  installer again. It needs no sudo after that.

sudo sh -eu <<'BRIG_ROOT'
cat > '/etc/apparmor.d/home.brigtest2..local.share.brig.data.bin.rootlesskit' <<'PROF'
...
PROF
apparmor_parser -r '/etc/apparmor.d/home.brigtest2..local.share.brig.data.bin.rootlesskit'
cat > /etc/udev/rules.d/99-brig-kvm-brigtest2.rules <<'RULE'
...
KERNEL=="kvm", SUBSYSTEM=="misc", MODE="0660", RUN+="/usr/bin/setfacl -m u:brigtest2:rw /dev/kvm"
KERNEL=="vhost-vsock", SUBSYSTEM=="misc", MODE="0660", RUN+="/usr/bin/setfacl -m u:brigtest2:rw /dev/vhost-vsock"
RULE
udevadm control --reload-rules
udevadm trigger --subsystem-match=misc --sysname-match=kvm
udevadm trigger --subsystem-match=misc --sysname-match=vhost-vsock
udevadm settle --timeout=10 || true
BRIG_ROOT
--- left behind in $HOME
ls: cannot access '/home/brigtest2/.local/share/brig': No such file or directory

Before the admin step, brigtest2 could not open either device from a user
namespace (unshare --user --map-root-user): Permission denied on both. An
admin fed the block, as printed, to sudo sh -eu. After it, the same probe
opened both, the profile was loaded, and the other two users' rule files kept
their hashes (998f808f..., 982b3773...) and their ACLs.

The next run of the installer as brigtest2, with a sudo shim that logs and
refuses every call first on PATH, installed to the end with an empty shim
log. So did a re-run of brig-ctl rootless. brig doctor was green, and
brig run -d ubuntu ~/proj booted a guest with qemu running as brigtest2.
Afterwards brigtest2 and everything made for it were removed.

🤖 Generated with Claude Code

@ananos
ananos changed the base branch from fix/rootless-per-user-device-grant to main September 25, 2026 22:40
For a user install on a host that is not prepared, install.sh printed the
missing host settings as a warning and went on. It downloaded and unpacked
the bundle, about 488 MB, and then brig-rootless-setup.sh asked for sudo. A
user without sudo was left at `[sudo] password for <user>:`, or without a
terminal, with a failed install. brig's install guide says a user install
asks for sudo at no point.

The preflight now covers every sudo call the setup can make: the device
grant, loading kvm and vhost_vsock, loading vhost_vsock at boot, the
AppArmor profile, and home directories an earlier sudo run left root-owned.
When any of them is missing and `sudo -n true` fails, it stops before the
download. It prints what is missing and one `sudo sh` block that fixes it
for this user and this prefix. An admin runs that block, and the next run
of the installer needs no sudo. With sudo that runs without a password,
nothing changes: the setup makes the settings at the end.

Missing packages and a missing subuid range stop the install as before,
since the setup never made them. The block now covers those too, and the
subuid range it offers starts past every range already handed out.

The setup no longer asks sudo to load a module the kernel does not have.
That was a password prompt for nothing.

This builds on the per-user grant file. The block writes
99-brig-kvm-<user>.rules, and the setup reads the grant back from the
devices.

tests/install-preflight.sh runs install.sh against a stub sudo, getfacl,
stat and sysctl, and points it at a bundle that does not exist. Without
sudo, it checks that the install stops before the fetch, writes nothing
under $HOME, and prints a valid block with the udev rule and the AppArmor
profile for this user. With sudo, it checks that the install goes on. On a
prepared host, it checks that no sudo is asked for. Against the previous
install.sh it fails the first check: the install goes on to fetch the
bundle.

Checked live on an Ubuntu 24.04 host, with a user who has no sudo. The
previous installer unpacked 488M into their home and then failed at
sudo. This one stopped with the block and left nothing in $HOME. An admin
ran the block as printed, and the user's next run installed without a
single sudo call. A microVM then booted with its monitor running as that
user.

Signed-off-by: Anastassios Nanos <ananos@nofire.ai>
@ananos
ananos force-pushed the fix/install-stop-without-sudo branch from d783015 to 7c6443c Compare September 25, 2026 22:40
@ananos
ananos marked this pull request as ready for review September 25, 2026 22:44
@ananos
ananos merged commit 3b1d7db into main Sep 25, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant