From a76ca9ae81d9bbf744c79f51e6dac26fe8bfc2b2 Mon Sep 17 00:00:00 2001 From: Wanjohi Date: Tue, 1 Sep 2026 15:26:59 +0300 Subject: [PATCH] fix(build): the root really is read-only, and two comments that overclaimed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three places where build/ said something the tree does not do. - fstab mounted `/` as `rw`. A box is started with `ro` on the kernel command line and `is_read_only: true` on the root device (every config in nesbox's tree agrees: examples/vm.json, test.json, run.local.json), so the virtio-blk device rejects writes whatever fstab asks for. `rw` here only made OpenRC's `root` service attempt a remount that has to fail. The Dockerfile already depended on the truth — it pre-creates /nestri/* at build time precisely because a runtime mkdir gets EROFS — so this makes fstab agree with the comment that was already right. - build/README.md said nesbox's jail image "extracts Mesa and virglrenderer" from this base. It extracts only Mesa. virglrenderer is the host half of the native-context protocol and nesbox builds its own, patched, from nesbox/patches/; nothing in this image carries it at all. - conf.d/nestri-user-env called the zink driver-forcing block "load-bearing" directly above three exports that are commented out, here and in the profile.d copy. Whether they should come back is a separate question; a comment insisting disabled lines are load-bearing tells the next reader the opposite of what the file does. The reasoning is kept, because it is still the reason to re-enable them, along with why both copies have to move together. Co-Authored-By: Claude Opus 5 (1M context) --- build/README.md | 15 +++++++++------ build/etc/conf.d/nestri-user-env | 16 ++++++++++------ build/etc/fstab | 8 +++++++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/build/README.md b/build/README.md index c43bedd0..4759b93a 100644 --- a/build/README.md +++ b/build/README.md @@ -55,12 +55,15 @@ Three things worth knowing about how this is put together: source, not a dependency, not a directory that 'looked convenient'."* Both are closed. `runtime_prod` from this Dockerfile — tagged `ghcr.io/nestrilabs/nestri/base:latest` — is a complete, bootable, Steam-less guest image, -and also the shared foundation other builds start from: nesbox's jailer -image (see `nesbox/build/`) extracts Mesa and virglrenderer from it so the -guest and host sides of the virtio-gpu native-context protocol never drift -apart. Whatever layers Proton and the Steam client on top of it is a closed -build outside this repo, by design — not something this repo names, links -to, or depends on. +and also the shared foundation other builds start from: nesbox's jail image +(see `nesbox/build/`) extracts **Mesa** from it so the guest and host sides of +the virtio-gpu native-context protocol never drift apart. Only Mesa — +`virglrenderer` is the host half of that protocol and nesbox builds its own, +patched, from `nesbox/patches/`; nothing in this image carries it. + +Whatever layers Proton and the Steam client on top of it is a closed build +outside this repo, by design — not something this repo names, links to, or +depends on. ## The nesinit gap diff --git a/build/etc/conf.d/nestri-user-env b/build/etc/conf.d/nestri-user-env index 13973ba3..ccde8729 100644 --- a/build/etc/conf.d/nestri-user-env +++ b/build/etc/conf.d/nestri-user-env @@ -11,12 +11,16 @@ XDG_SESSION_TYPE="wayland" XDG_SESSION_DESKTOP="nestri" DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus" -# Driver forcing, mirrored from /etc/profile.d/nestri-env.sh. That file only -# runs for login shells, and nothing here is a login shell — every service -# below runs from OpenRC. Capture happens through a Vulkan layer, so a -# process that reached the GPU via native OpenGL would render fine and -# capture nothing; zink is what makes such a process capturable at all. -# These are load-bearing. Keep them in step with the profile.d copy. +# Driver forcing — currently off, in both copies. Kept, commented, because +# the reasoning still applies if it is ever needed again: capture happens +# through a Vulkan layer, so a process reaching the GPU via native OpenGL +# would render fine and capture nothing, and zink is what makes such a +# process capturable at all. Nothing has needed it so far. +# +# /etc/profile.d/nestri-env.sh carries the same block, also commented, and +# only runs for login shells — nothing here is one, every service below runs +# from OpenRC. If these are ever re-enabled, re-enable both: one copy on and +# one off means services and shells reach the GPU by different paths. #__GLX_VENDOR_LIBRARY_NAME="mesa" #MESA_LOADER_DRIVER_OVERRIDE="zink" #GALLIUM_DRIVER="zink" diff --git a/build/etc/fstab b/build/etc/fstab index 92284f56..b183fda8 100644 --- a/build/etc/fstab +++ b/build/etc/fstab @@ -1,4 +1,10 @@ -/dev/vda / ext4 rw,relatime 0 1 +# `ro`, matching how a box is actually started: nesbox passes `ro` on the +# kernel command line and marks the root device `is_read_only: true` (see +# nesbox's examples/vm.json), so the virtio-blk device refuses writes at the +# device level. Saying `rw` here does not make it writable — it only asks +# OpenRC's `root` service to attempt a remount that the device must reject. +# Everything a running box writes to is a tmpfs or a share below. +/dev/vda / ext4 ro,relatime 0 1 devtmpfs /dev devtmpfs rw,nosuid 0 0 proc /proc proc rw,nosuid,nodev,noexec 0 0 sysfs /sys sysfs rw,nosuid,nodev,noexec 0 0