Commit Graph
19 Commits
Author SHA1 Message Date
Wanjohi ebf31b5fe8 fix(build): the guest carries the libraries Proton's media plugins need (#405)
**Problem.** Proton's GStreamer plugins link `libvpx`, `speex`,
`libtheora`, `libvdpau` and `jsoncpp`, and neither Proton nor the guest
image carries them. Boxes log:

```
Failed to load plugin '.../gstreamer-1.0/libgstlibav.so': libvpx.so.12: cannot open shared object file
Failed to load plugin '.../gstreamer-1.0/libgstspeex.so': libspeex.so.1: cannot open shared object file
```

Wine's media stack then has no decoders, so a game whose videos go
through it plays them as nothing.

**Scope.**
- Not new. The stock `11.0-20261005` Proton and the patched `-n1` build
need exactly the same set.
- The fleet logged it on 2026-10-10 and again on 2026-10-15.

**Fix.** These five packages are added to the guest's runtime package
list.
- They were found by listing every `NEEDED` library of each published
Proton against this image; they were the whole gap.
- They track the sonames Proton was built against, as the new comment
says.

**Verification.** In progress: the image is building, and the library
check is rerun against it for both Protons.
2026-10-15 19:28:31 +03:00
Wanjohi c0174628cd fix(build): give the guest's OpenGL driver its EGL and GLX frontends
Mesa was built with zink as its only Gallium driver and every frontend disabled, so a game rendering with OpenGL found no GL and showed a black screen. EGL, GLX, GBM and GLES2 are enabled, with the x11 platform for Xwayland clients.
2026-10-14 11:23:35 +03:00
Wanjohi 514212bbbe Host agent runs as root; NVIDIA host programs ship in the base image (#366)
- **Installer:** piped into `sudo`, installs to `/usr/local/bin`, and
hands onboarding `/var/lib/nestri`. Root lets the host agent jail each
box under its own uid and give guests a network. A host that ran the
agent as the sudo user has that state copied over (never moved), so it
keeps its machine identity and its downloads. Pins host agent 0.2.4.
- **Base image:** `vhost-user-nvgpu` and `nvgpu-userspace`, static
(musl), from the same `NVGPU_REF` as the guest driver and Vulkan layer,
under `/boot/host`. The host agent takes them out at unpack, as it does
the kernel, and forwards the GPU when it finds the NVIDIA driver loaded.

Merge after the host agent 0.2.4 release: the installer pins it.
2026-10-07 19:59:29 +00:00
Wanjohi 4e4dd8896f build: ship the guest kernel inside the image, publish from the build box (#361)
A `kernel-build` stage runs `kernel-build.sh` and puts the result at
`/boot/vmlinux`; host onboarding takes it out beside the root image, so
kernel and image (and their shared NVGPU_REF) always ship as one pair.
`make push` publishes `:latest` and a commit tag from the build box.

Built on the build box: `/boot/vmlinux` is 24 MB, and
`vmlinux.nvgpu-rev` is beside it.
2026-10-07 15:43:31 +00:00
DatCaptainHorse 459f787360 feat: proton-cachyos returns 2026-10-05 16:25:33 +03:00
DatCaptainHorse 030dcc5a8c feat: RT for audio 2026-10-05 14:19:11 +03:00
Wanjohi 8c61cb5cbb feat(build): put virtio-nvgpu's Vulkan layer into the guest rootfs (#356)
On an NVIDIA host, NVIDIA's Vulkan driver in the guest lists ray
tracing, optical flow, binary import and CUDA kernel launch, then fails
`vkCreateDevice` with `VK_ERROR_INITIALIZATION_FAILED` for each of them.
An engine that enables what it is offered does not start. virtio-nvgpu's
guest layer (`vklayer/`, nestrilabs/virtio-nvgpu#5) hides those
extensions. It acts only on an NVIDIA device in a guest that has the
virtio-nvgpu driver, so on AMD and Intel boxes it loads and does
nothing.

- A new `nvgpu-layer-build` stage builds the layer from virtio-nvgpu at
`NVGPU_REF`, the same setting the kernel build uses for the guest
driver. The commit is recorded in `/usr/share/nestri/virtio-nvgpu.rev`.
- The layer and its manifest go in `/usr/lib` and
`/usr/share/vulkan/implicit_layer.d`. The missing-library check covers
the layer.

**Merge after nestrilabs/virtio-nvgpu#5.** The default `NVGPU_REF=dev`
has no `vklayer/` until that PR lands, so `make build` fails at this
stage before then.

Built on nestripc-1 with `NVGPU_REF=feat/v0.2-compute` (virtio-nvgpu
112eac4) and pushed:
- `ghcr.io/nestrilabs/nestri/base:latest` sha256:152a4485…
- `ghcr.io/nestrilabs/nesbox/jail:latest` sha256:df813051…, rebuilt on
that base from nesbox dev 6d37597, which includes the vhost-user
forwarding

Measured on box2 (RTX 3060, 595.104.02) with virtio-nvgpu's vkrt probe:
with the layer on, a plain device is created and none of the seven
extensions are offered. With it off, all seven are offered and fail with
-3.
2026-10-04 02:30:10 +00:00
DatCaptainHorse ef32d5f394 fix: Remove proton leftovers 2026-10-03 20:47:21 +03:00
Wanjohi 01d6f2302d build: put virtio-nvgpu's Vulkan layer into the guest rootfs
On an NVIDIA host the guest's Vulkan driver offers ray tracing, optical
flow and a few others it cannot create a device with, and an engine that
enables them does not start. virtio-nvgpu's layer hides them; it acts
only on a forwarded NVIDIA device, so AMD and Intel boxes are unaffected.

Built from virtio-nvgpu at NVGPU_REF, the ref the kernel build already
takes the guest driver from, and recorded in the image.
2026-10-02 22:43:03 +03:00
DatCaptainHorseandClaude Sonnet 5.5 d0ec87a139 feat: attach a shell to a running box
The host can now ask a box for a shell on a pseudo-terminal, the way a container
runtime attaches to a container. `HostToGuest::Attach` starts the process, and
the guest then dials the host on a vsock port of its own (7001) and carries the
terminal's bytes over a small framed stream: data both ways, a resize, a hangup,
and the exit status last. A screenful of output on the JSON-lines control channel
would hold every other message in the box behind it, which is why it is not
there. A failure to start is the exception, and is said on the control channel
because nothing has connected to the data port yet.

A shell is not a launch: it never ends the box, and the box ending ends it. It
is started through the same reaper as everything else, so it cannot become the
zombie that exists to be prevented. With a terminal on the other end the PTY is
ordinary; without one it is put in raw mode so a command run for its output gets
its bytes back unrewritten. Closing the stream hangs the shell up, process group
and all.

The frame codec is a pure bytes-in, frames-out module in nesprotocol with a
payload cap and no skipping of unknown tags, since a length read from a guest is
read across a trust boundary. No version bump: adding a message does not need
one, and a guest that predates it simply never dials.

The runtime stage gains strace, lsof and less, so a root shell in a box is not
one that cannot trace a process.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 17:09:15 +03:00
DatCaptainHorseandClaude Sonnet 5.5 71801261a4 fix: get Rust from rustup in the builder stage
The distribution's rust package is built against the distribution's LLVM, and
when the two repositories this image draws from disagree about llvm-libs, rustc
itself fails to start with a symbol-lookup error, before any of our code is
involved and in every stage that builds Rust. rustup's toolchain links nothing
of the distribution's, so `rustup default stable` replaces the package.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 17:09:15 +03:00
DatCaptainHorseandClaude Sonnet 5.5 85e6f19977 feat: build umu-launcher into the guest image
`umu-run` is how a title that is not Steam's is launched, so the game fixes
Proton carries apply outside Steam. It is built from a pinned tag in its own
stage rather than installed from the distribution, whose package declares a
long list of lib32 libraries and desktop packages for the Steam Linux Runtime
container this image never runs.

It is built against the distribution's urllib3 and pyzstd instead of the copies
it can vendor: those are built from source with pinned build tooling, and a
rolling distribution moved past a pin (setuptools-scm 10 against a <10
ceiling) and failed the build. The image adds python-xlib, python-urllib3 and
python-pyzstd, none of which pull in anything 32-bit.

Two checks keep it honest. umu-run has to start, because a missing Python module
otherwise shows up as a game that never starts and reads like a script failure;
and no lib32 package may be installed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 17:09:15 +03:00
DatCaptainHorseandClaude Sonnet 5.5 3149a9d4b1 feat: mount a compatibility layer image, and take Proton out of the rootfs
The boot descriptor gains `images`: read-only EROFS images mounted on their
own, with no writable layer over them. nesinit mounts them first, before
overlays and shares, with the same nosuid/nodev guards every layer has and
without noexec because what is in one is run. CONTROL_VERSION moves to 5: the
descriptor refuses fields it does not know, and a guest image without Proton is
useless to a host that does not send one, so the mismatch is named at the
handshake.

The guest rootfs no longer contains Proton. The checks that used to guard the
in-image copy (every library its programs and Wine's core link, an interpreter
behind the entry point) move to a compat_check stage that verifies the Proton
named by PROTON_IMAGE and leaves a marker in the image saying which one. The
leaf stages copy that marker out of it so the stage cannot be skipped as
unused. With nothing at a Proton path, a box started without one fails saying
where it looked.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 02:20:41 +03:00
cf46bf4d12 feat: pyrowave support (#354)
At this point, why not..

Calling it `nespyro` since it's slightly modified, uses slang shader
language instead, along other things..

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:53:19 +03:00
DatCaptainHorse a493157d41 fix: nescope presentation handling, add mold to rootfs builds, update
mesa rev
2026-09-30 14:07:03 +03:00
451b495de6 feat: controller/gamepad support (#350)
Adds `nesgamepad`, basically "diet-coke vimputti" for Nestri's microVM
needs here.

Comes with direct mapping for:
- Sony
  - DualShock 4 (v2), DualSense
- Microsoft
  - Xbox 360 pad, Xbox One S pad
- Nintendo
  - Pro Controller
- Generic pad for unknown controllers

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 17:50:02 +03:00
0811f57f1a feat: media bitrate control, HDR (#346)
Fixes: #335 

Still a work-in-progress.

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Wanjohi <elviswanjohi47@gmail.com>
2026-09-25 12:13:34 +03:00
6811c93d51 feat: nescapture capture improvements and drive mounts (#337)
Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 22:58:22 +03:00
8246aa5538 feat: resident guest init (#333)
Get this thing going..







<!-- greptile_comment -->

<!-- greptile_summary -->

<h2><a
href="https://app.greptile.com/api/retrigger?id=63134761"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/RetriggerDark.svg?v=1"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/Retrigger.svg?v=1"><img
alt="Retrigger"
src="https://greptile-static-assets.s3.amazonaws.com/badges/Retrigger.svg?v=1"
align="right"></picture></a>Confidence Score: 5/5</h2>

The PR appears safe to merge; all previous findings are resolved and the
latest readiness change introduces no established actionable regression.

<h3>Summary</h3>

- Establishes required guest filesystems, runtime directories, device
permissions, and service processes.
- Reports initialization and service deaths over the lifecycle channel.
- Supports launch, restart, and shutdown commands for a resident guest.
- Separates service and workload identities and configures per-launch
runtime environments.
- Removes the currently inactive nescope screenshot option and makes
capture-chain verification fail explicitly when compositor readback is
unavailable.
- Reworks the guest image around `nesinit` as PID 1 without a
distribution service manager.

<h3>Diagram</h3>

```mermaid
sequenceDiagram
    participant Host
    participant Init as nesinit
    participant FS as Guest filesystems
    participant Services as Service stack
    participant Workload

    Init->>Host: Ready(protocol version)
    Host->>Init: Boot(mount descriptors)
    Init->>FS: Establish and mount shares
    Init->>Services: Spawn services in order
    Services-->>Init: Required sockets ready
    Init->>Host: Initialized(service names)
    Host->>Init: Launch(id, exec, on_exit)
    Init->>Workload: Spawn with isolated UID/runtime
    Init->>Host: Started(id)
    Workload-->>Init: Exit status
    Init->>Host: WorkloadExited(id, status)
    Host->>Init: Launch / Restart / Shutdown
```

<sub>Reviews (4) · Last reviewed commit: ["fix(nesinit): readiness is a
socket
that..."](https://github.com/nestrilabs/nestri/commit/731d34df9df30463f67963363424cb9487e89196)</sub>

<!-- /greptile_comment -->

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 14:45:13 +03:00