Skip to content

fix(bundle): Run brig-ctl's ctr inside the rootless namespace - #8

Merged
ananos merged 1 commit into
mainfrom
fix/brig-ctl-ctr-rootless
Sep 25, 2026
Merged

ananos merged 1 commit into
mainfrom
fix/brig-ctl-ctr-rootless

Conversation

@ananos

@ananos ananos commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Summary

brig-ctl ctr failed on a rootless install:

$ brig-ctl ctr tasks ls
ctr: cannot access socket unix:///run/containerd/containerd.sock: stat unix:///run/containerd/containerd.sock: no such file or directory

Two things were wrong, and #4 surfaced both. ctr stats --address as a file
path before it dials, and brig-env.sh writes the address with a unix://
scheme, which nerdctl wants. Since #4, brig-ctl takes the address from
brig-env.sh, so ctr failed that stat on every install, root or rootless, and
brig-ctl status listed no plugins. On top of that, a rootless install's socket
exists only inside the rootlesskit namespace. nerdctl enters that namespace by
itself; ctr does not.

Changes

  • brig-ctl strips the unix:// scheme for ctr.
  • For a caller who is not root on a rootless bundle (the test brig-env.sh
    makes), ctr runs through containerd-rootless-setuptool.sh nsenter, which the
    bundle already ships with nerdctl. It handles the --detach-netns case and
    the working directory the way nerdctl's own tooling does.
  • With no rootless containerd running, it says how to start one, instead of
    failing inside nsenter on a missing child_pid.
  • ctr and status share that path. nerdctl and run need no change.
  • tests/brig-ctl.sh, run by the Script tests CI step (the same step as fix(rootless): Give each user a device grant of their own #6 and
    fix(install): Name the bundle in the install summary #9, word for word).

Testing

tests/brig-ctl.sh generates brig-ctl with the build's own write_brig_ctl,
for a bundle with and without the rootless path, and runs it against a stub
ctr and setup tool that log their argv:

$ sh tests/brig-ctl.sh
ok - a rootless caller runs ctr in the namespace, on a bare path
ok - status lists plugins through the namespace
ok - with no daemon it says how to start one
ok - a plain bundle runs ctr directly, on a bare path

The same test against main's build-bundle.sh:

$ sh tests/brig-ctl.sh
ctr --address unix:///run/containerd/containerd.sock --namespace brig version
FAIL: ctr did not go through the rootless namespace

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

Live, on an Ubuntu 24.04 host with a rootless user install

brig-ctl generated from this branch, in the user's installed tree:

$ brig-ctl ctr version
Client:
  Version:  v2.3.5
Server:
  Version:  v2.3.5
  UUID: fc91f9cf-0f39-4403-b062-342dbd563d54
$ brig-ctl ctr tasks ls          # with brig run -d ubuntu up
TASK                                                                PID        STATUS
ec567fcf55634132696f93f605b841f6029a71949e686fa45733868754ef4238    1267621    RUNNING
$ brig-ctl status | tail -3
io.containerd.snapshotter.v1              native                   linux/amd64    ok
io.containerd.snapshotter.v1              overlayfs                linux/amd64    ok
io.containerd.snapshotter.v1              zfs                      linux/amd64    skip

The v0.1.0-rc8 brig-ctl on the same install (main's generator reproduces it
byte for byte), retargeted to that prefix:

$ brig-ctl ctr version
Client:
  Version:  v2.3.5
ctr: cannot access socket unix:///run/containerd/containerd.sock: stat unix:///run/containerd/containerd.sock: no such file or directory
exit=1

and its status ended after the unit's journal with no plugin table.

🤖 Generated with Claude Code

`brig-ctl ctr` failed on a rootless install:

  $ brig-ctl ctr tasks ls
  ctr: cannot access socket unix:///run/containerd/containerd.sock: stat
  unix:///run/containerd/containerd.sock: no such file or directory

Two things were wrong. ctr stats --address as a file path before it dials,
and brig-env.sh writes the address with a unix:// scheme, which nerdctl
wants. Since brig-ctl takes the address from brig-env.sh, ctr failed that
stat on every install, root or rootless, and `brig-ctl status` listed no
plugins. And on a rootless install the socket exists only inside the
rootlesskit namespace. nerdctl enters that namespace by itself; ctr does
not.

brig-ctl now strips the scheme for ctr. For a caller who is not root on a
rootless bundle, it runs ctr through `containerd-rootless-setuptool.sh
nsenter`, which the bundle already ships with nerdctl. With no rootless
containerd running, it says how to start one. `ctr` and `status` share
that path. The nerdctl and run subcommands need no change.

tests/brig-ctl.sh generates brig-ctl with the build's own function, for a
bundle with and without the rootless path, and runs it against a stub ctr
and setup tool. It checks that a rootless caller's ctr goes through the
namespace on a bare socket path, that status does the same, that a missing
daemon gets a hint, and that a plain bundle runs ctr directly on a bare
path. Against the previous build-bundle.sh it fails the first check, with
ctr called directly on unix:///run/containerd/containerd.sock.

Checked live on an Ubuntu 24.04 host with a rootless user install. `ctr
version` now reports the server, `ctr tasks ls` lists a running
sandbox's task, and `status` lists the snapshotter plugins. The previous
brig-ctl, on the same install, fails with the error above and lists no
plugins.

Signed-off-by: Anastassios Nanos <ananos@nofire.ai>
@ananos
ananos force-pushed the fix/brig-ctl-ctr-rootless branch from 8940184 to 7084c94 Compare September 25, 2026 22:45
@ananos
ananos marked this pull request as ready for review September 25, 2026 22:48
@ananos
ananos merged commit 1821c04 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