Skip to content

evidence(containers): the SBSA image RUNS on Tegra — Orin generates on the GPU - #422

Merged
localai-bot merged 1 commit into
mainfrom
row/CONTAINERS-W6-TEGRA
Aug 11, 2026
Merged

evidence(containers): the SBSA image RUNS on Tegra — Orin generates on the GPU#422
localai-bot merged 1 commit into
mainfrom
row/CONTAINERS-W6-TEGRA

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

W6's Tegra determination — and it contradicts what the spec predicted. Refs #170.

The risk entry said Thor and Orin "are Tegra/L4T with a different CUDA runtime" and that the arm64 image made no claim there. It runs. There is no CUDA-version wall, and no separate Tegra lane is needed: one SBSA image serves both arm64 families.

Measured on Jetson AGX Orin (sm_87, L4T R36.4.3, Docker 27.5.1)

Running the image built on GB10, unmodified:

axis result
validator config + layout verified; /health 200, /version 200, declared healthcheck passed, clean SIGTERM
model Qwen3-0.6B (rev c1899de2…, 1.5 GB) loads and generates: "The capital of France is"" Paris. …", 24 completion tokens
GPU tegrastats GR3D_FREQ 95–97% during a 120-token generation, vs 14–15% idle

That last row is the one /health cannot make — on Orin or on GB10. It's the difference between "the server came up with a GPU attached" and "the GPU produced the tokens".

The invocation differs, and all three cases fail differently

flags Tegra behaviour
--gpus all alone refused by the runtime hook
--runtime nvidia alone starts, no driver mounted, dies on libcuda.so.1: cannot open shared object file
--runtime nvidia --gpus all works

The middle case is the trap: the container comes up and dies on a missing library, which reads as a broken image rather than a wrong flag. docs/USAGE.md documented only --gpus all and was therefore wrong for every Jetson; now fixed.

Two portability defects the second box exposed

Both invisible on GB10 because that box happened to match:

  • validate-container-image.py used docker stop --timeout, which is newer-Docker only; Orin's 27.5.1 rejects it. -t works on both.
  • /models must be readable by uid 1000. On GB10 the model was owned by uid 1000, so mode 0600 worked; on Orin (files owned by 65535) the server initialised CUDA and then died on safetensors: cannot open file — which reads like a corrupt checkpoint. Now documented.

Running a deliberately different second box is what surfaced these; a second GB10 would have found none of them.

A wrong hypothesis, killed by test rather than shipped

I assumed the injected driver path simply wasn't on the loader search path and tried patching LD_LIBRARY_PATH to include /usr/lib/aarch64-linux-gnu/nvidia. Still not found — because with --runtime alone the driver isn't mounted at all. No Dockerfile change is needed; the nvidia runtime handles ldconfig itself in csv mode.

Scope

Orin (sm_87) only. Thor (sm_110) has never been probed and inherits nothing from this. Nothing is published to GHCR.

Gates

scripts/agent-preflight.sh --staged exits 0; agent-record, container matrix, workflow guard and public-doc tables all green.

🤖 Generated with Claude Code

…on the GPU

FOLLOWING_AGENTS_PROTOCOL

W6's Tegra determination, and it contradicts what this spec predicted. The risk
entry said Thor and Orin "are Tegra/L4T with a different CUDA runtime" and that
the arm64 image made no claim there. It runs. There is no CUDA-version wall,
and no separate Tegra lane is needed: ONE SBSA image serves both arm64
families.

Measured on a Jetson AGX Orin Developer Kit (sm_87, L4T R36.4.3, Docker 27.5.1,
Kairos immutable OS), running the image built on GB10:

  validator  config + layout verified; /health 200, /version 200, declared
             healthcheck passed, clean SIGTERM, on --runtime nvidia --gpus all
  model      Qwen3-0.6B (rev c1899de289a04d12100db370d81485cdf75e47ca, 1.5 GB)
             loads and GENERATES: "The capital of France is" -> " Paris. ..."
             24 completion tokens
  gpu        tegrastats GR3D_FREQ 95-97% during a 120-token generation, against
             14-15% idle -- decode runs on the Orin GPU, not a CPU fallback

That last line is the one /health could not make, on Orin or on GB10.

THE INVOCATION DIFFERS, and all three cases fail differently:

  --gpus all alone            REFUSED by the runtime hook
  --runtime nvidia alone      starts, no driver, dies on libcuda.so.1 missing
  --runtime nvidia --gpus all works

The middle case is the trap: the container comes up and dies on a missing
library, which reads as a broken image rather than a wrong flag. docs/USAGE.md
documented only `--gpus all` and was therefore wrong for every Jetson.

Two portability defects the second box exposed, both invisible on GB10 because
that box happened to match:

- validate-container-image.py used `docker stop --timeout`, which is
  newer-Docker only; Orin's 27.5.1 rejects it. `-t` is accepted by both.
- /models must be READABLE BY UID 1000. On GB10 the model was owned by uid 1000
  so mode 0600 worked; on Orin (files owned by 65535) the server initialised
  CUDA and died on `safetensors: cannot open file`, which reads like a corrupt
  checkpoint. Now documented.

A wrong hypothesis, killed by test rather than shipped: I assumed the injected
driver path just was not on the loader search path and tried patching
LD_LIBRARY_PATH to include /usr/lib/aarch64-linux-gnu/nvidia. Still not found --
because with --runtime alone the driver is not mounted at all. No Dockerfile
change is needed; the nvidia runtime handles ldconfig itself in csv mode.

Scope: Orin (sm_87) only. Thor (sm_110) has never been probed and inherits
nothing from this. Nothing is published to GHCR.

Issues: #170

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [Claude Code]
@localai-bot
localai-bot merged commit 94919b4 into main Aug 11, 2026
12 of 14 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.

2 participants