Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ jobs:
set -eu
scripts/build-bundle.sh --arch "${{ matrix.arch }}" --version ci --variant generic-boot --out dist

# install.sh retargets a user install by rewriting the layout the bundle
# was generated with, which it reads from here.
- name: Check the bundle records its layout
run: |
set -eu
p="$(ls dist/*.pins.env)"
for k in PREFIX DATA_DIR RUN_DIR; do
grep -q "^$k=/" "$p" || { echo "pins.env does not record $k"; exit 1; }
done

- uses: actions/upload-artifact@v4
with:
name: bundle-${{ matrix.arch }}
Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,17 @@ $ brig-ctl rootless
$ brig run claude ~/code/demo
```

Or skip root entirely. Run `install.sh` as a normal user and it installs into
`~/.local/share/brig`, with the launchers in `~/.local/bin`, and starts the
rootless daemon for you:

```console
$ curl -fsSL https://raw.githubusercontent.com/NOFireAI/brig-standalone-linux/main/install.sh | sh -
$ ~/.local/bin/brig run claude ~/code/demo
```

[docs/rootless.md](docs/rootless.md) has the detail, including the two things
that still need root once per host and how to build a bundle that installs into
a home directory.
that still need root once per host, and what a home install gives up.

## Driving the runtime by hand

Expand Down
48 changes: 36 additions & 12 deletions docs/rootless.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,40 @@ monitor is the host-side process that boots it.

## Installing into a home directory

The layout is fixed at build time, so a bundle built for a prefix under `$HOME`
can be unpacked by the user who runs it, with no root anywhere in the install:
`install.sh --user` puts the whole thing under `$HOME` and touches nothing
else. It is what a non-root caller gets by default, so on a machine where you
have no root at all:

```console
$ curl -fsSL https://raw.githubusercontent.com/NOFireAI/brig-standalone-linux/main/install.sh | sh -
$ ~/.local/bin/brig doctor && ~/.local/bin/brig run claude ~/code/demo
```

The tree lands in `~/.local/share/brig`, as `data/` and `agent/` the way
`/var/lib/brig` holds them; the launchers go in `~/.local/bin` and the socket
in `$XDG_RUNTIME_DIR`. The last stage runs `brig-rootless-setup.sh`, so the
daemon is up when the installer returns. `brig-ctl uninstall` takes it down
again as the same user.

The published tarball is generated for `/var/lib/brig/data`, so a user install
rewrites that path once the tree is in place. Nine generated files carry it:
`etc/brig-env.sh`, `etc/*.toml`, the systemd units and the scripts in `bin/`.
No binary does. The installer greps for the old prefix afterwards and fails if
any of it survived, which is what keeps that list honest as the bundle grows.

Two things differ from a root install. A thin pool needs `losetup` and
`dmsetup`, which a user namespace does not get, so a user install is overlayfs
only. And the tree is one copy per user where a root install is shared, so with
root and several users, `brig-ctl rootless` against one shared install is the
better trade.

The host prerequisites above still apply. `install.sh --user` reports both
before it unpacks anything, and the rootless setup asks sudo once to fix them.
The AppArmor profile names this prefix's rootlesskit, so a profile written for
`/var/lib` does not cover a tree in `$HOME`.

Building for a prefix directly is still an option, for an air-gapped host or a
layout of your own:

```console
$ PREFIX=$HOME/.local/share/brig/data \
Expand All @@ -97,13 +129,5 @@ $ PREFIX=$HOME/.local/share/brig/data \
./scripts/build-bundle.sh --arch amd64 --version v0.2.0 --out dist
```

Unpack it, write a launcher that sources `etc/brig-env.sh` and execs
`bin/brig`, then run `bin/brig-rootless-setup.sh`. The two host prerequisites
above still apply, and the AppArmor profile has to name this prefix's
rootlesskit rather than another one's.

The prefix is baked into the generated configs, so a bundle built for one home
does not serve another. Making one tarball serve any user means rewriting those
paths at unpack time, which is what an `install.sh --user` mode would do. The
files that carry them are text: `etc/brig-env.sh`, `etc/*.toml` and the
generated scripts in `bin/`.
`pins.env` records that layout, so `install.sh` retargets from what the bundle
was built with rather than assuming the default.
Loading
Loading