Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d1ef777
chore(deps): bump actions/checkout from 6.0.3 to 7.0.0 (#2038)
dependabot[bot] Jun 29, 2026
c7202af
chore(deps): bump actions/attest from 4.1.0 to 4.1.1 (#2037)
dependabot[bot] Jun 29, 2026
8cb16de
chore(deploy): use OCI registry for cert-manager Helm chart (#2041)
lunarwhite Jun 29, 2026
afc06dd
fix(supervisor): drop sandbox child capability bounding set (#2001)
alangou Jun 29, 2026
a5161d0
refactor(server): normalize compute driver config acquisition (#1974)
elezar Jun 29, 2026
a226806
test(e2e): run gpu workloads from manifest (#1709)
elezar Jun 30, 2026
f27ff15
fix(providers): reserve credential placeholder revisions (#2049)
johntmyers Jun 30, 2026
474d2d4
fix(CONTRIBUTING): update label format for good first issues (#2056)
jgarciao Jun 30, 2026
ed0026a
fix(helm): generate namespace-aware SANs in certgen and cert-manager …
akram Jun 30, 2026
0a25fdf
refactor(core): remove unused extra bind addresses (#2059)
elezar Jun 30, 2026
5477e2f
docs(mcp): fix granular policy lifecycle examples (#2066)
shiju-nv Jun 30, 2026
914da33
feat(kubernetes): add combined topology config surface (#2074)
TaylorMutch Jun 30, 2026
450685c
fix(drivers): reject whitespace in mount fields (#2086)
elezar Jul 1, 2026
45614a3
refactor(api): remove SandboxTemplate.volume_claim_templates (#2088)
elezar Jul 1, 2026
abcd15d
feat(helm): add TLS termination for Envoy Gateway ingress (#2015)
zhaohuabing Jul 1, 2026
45060f4
feat(agents): add manifest-driven gator agent (#1826)
johntmyers Jul 1, 2026
43bb030
feat(docker,podman): add SELinux label support for bind mounts (#2092)
bergmannf Jul 2, 2026
5f9bf9c
test(e2e): run rootless podman on ubuntu host (#2119)
elezar Jul 2, 2026
6461677
feat(policy): accept numeric UIDs for sandbox process identity (#1973)
sjenning Jul 2, 2026
f852d07
docs: add Hermes Agent to supported agents table (#2131)
mesutoezdil Jul 3, 2026
6252aa1
rfc-0006: add driver config passthrough proposal (#1589)
elezar Jul 6, 2026
7b267ba
fix(tui): route warning logs to status bar instead of stderr
r3v5 Jul 7, 2026
f8bcdbc
feat(tui): add ForwardWarnings event variant
r3v5 Jul 7, 2026
97862a8
chore(tui): remove tracing dependency
r3v5 Jul 7, 2026
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
2 changes: 2 additions & 0 deletions .agents/skills/debug-openshell-cluster/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ openshell logs <sandbox-name>
| CLI TLS error | Local mTLS bundle does not match server cert/CA | Check `~/.config/openshell/gateways/<name>/mtls/` |
| Image pull failure | Gateway or sandbox image cannot be pulled | Runtime events and image pull credentials |
| `K8s namespace not ready` with `envoy-gateway-openshell.yaml: the server could not find the requested resource` | Optional Gateway API manifest was applied without Envoy Gateway CRDs, or k3s Helm controller startup exceeded the namespace wait | Apply `deploy/kube/manifests/envoy-gateway-openshell.yaml` manually only after Envoy Gateway is installed and `grpcRoute` is enabled |
| HTTPS ingress (`grpcRoute.gateway.listener.protocol=HTTPS`) connection resets or TLS handshake hangs | Envoy terminates TLS but the gateway pod still expects TLS, so the plaintext backend hop fails | Set `server.disableTls=true` so Envoy forwards plaintext to the pod; verify the listener `certificateRefs` Secret exists in the release namespace and `openshell status` over `https://<host>` |
| HTTPS ingress returns `Unauthenticated` after connecting | TLS terminates at Envoy, so the gateway never sees a client cert; no OIDC issuer is configured for identity | Configure `server.oidc.issuer` and register with `openshell gateway add https://<host> --oidc-issuer <url>`, or set `server.auth.allowUnauthenticatedUsers=true` for a trusted-proxy/dev cluster |

## Reporting

Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/e2e-gpu-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ jobs:
OPENSHELL_REGISTRY_NAMESPACE: nvidia/openshell
OPENSHELL_REGISTRY_USERNAME: ${{ github.actor }}
OPENSHELL_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
CONTAINER_ENGINE: docker
OPENSHELL_E2E_DOCKER_GPU: "1"
# NVIDIA-managed Ubuntu base used as the GPU probe target: it has the
# filesystem layout CDI injection expects (ldconfig, populated /usr/bin)
# which the distroless gateway runtime lacks. Consumed by the prereq
# probe below and by the e2e tests in e2e/rust/tests/gpu_device_selection.rs.
# probe below and by the e2e tests in e2e/rust/tests/gpu/device_selection.rs.
OPENSHELL_E2E_GPU_PROBE_IMAGE: "nvcr.io/nvidia/base/ubuntu:noble-20251013"
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
Expand All @@ -65,5 +66,8 @@ jobs:
docker info --format '{{json .CDISpecDirs}}'
docker run --rm --device nvidia.com/gpu=all "${OPENSHELL_E2E_GPU_PROBE_IMAGE}" nvidia-smi -L

- name: Build GPU workload images
run: mise run --no-deps --skip-deps e2e:workloads:build

- name: Run tests
run: mise run --no-deps --skip-deps e2e:docker:gpu
166 changes: 114 additions & 52 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,6 @@ jobs:
- suite: rust-docker
cmd: "mise run --no-deps --skip-deps e2e:rust"
apt_packages: "openssh-client"
- suite: rust-podman
cmd: "mise run --no-deps --skip-deps e2e:podman"
apt_packages: "openssh-client podman"
- suite: rust-podman-rootless
cmd: "mise run --no-deps --skip-deps e2e:podman:rootless"
apt_packages: "openssh-client podman uidmap"
rootless: true
- suite: mcp
cmd: "mise run --no-deps --skip-deps e2e:mcp"
apt_packages: ""
Expand Down Expand Up @@ -72,7 +65,7 @@ jobs:

- name: Check out MCP conformance tests
if: matrix.suite == 'mcp'
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: modelcontextprotocol/conformance
# Pin after v0.1.16 to include the tools_call client scenario fix.
Expand All @@ -89,28 +82,6 @@ jobs:
- name: Log in to GHCR with Docker
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

- name: Log in to GHCR with Podman
if: startsWith(matrix.suite, 'rust-podman')
run: echo "${{ secrets.GITHUB_TOKEN }}" | podman login ghcr.io -u "${{ github.actor }}" --password-stdin

- name: Set up rootless Podman user
if: matrix.rootless
run: |
useradd -m openshell-test
echo "openshell-test:100000:65536" >> /etc/subuid
echo "openshell-test:100000:65536" >> /etc/subgid
mkdir -p "/run/user/$(id -u openshell-test)"
chown openshell-test: "/run/user/$(id -u openshell-test)"
chmod 700 "/run/user/$(id -u openshell-test)"
chown -R openshell-test: .
mkdir -p /home/openshell-test/.cache/mise /home/openshell-test/.cargo /home/openshell-test/.local/state/mise
chown -R openshell-test: /home/openshell-test/.cache /home/openshell-test/.cargo /home/openshell-test/.local
install -m 0755 "$(command -v mise)" /usr/local/bin/mise
chmod a+x /root /root/.local /root/.local/bin
for dir in /root/.cargo /root/.rustup /root/.local/share/mise /opt/mise; do
[ -d "$dir" ] && chmod -R a+rX "$dir"
done

- name: Install Python dependencies and generate protobuf stubs
if: matrix.suite == 'python'
run: uv sync --frozen && mise run --no-deps python:proto
Expand All @@ -119,27 +90,118 @@ jobs:
env:
OPENSHELL_SUPERVISOR_IMAGE: ${{ format('ghcr.io/nvidia/openshell/supervisor:{0}', inputs.image-tag) }}
OPENSHELL_MCP_CONFORMANCE_CLIENT_IMAGE: ${{ format('openshell-mcp-conformance-client:{0}', inputs.image-tag) }}
E2E_CMD: ${{ matrix.cmd }}
run: ${{ matrix.cmd }}

e2e-podman-rootless:
name: E2E (rust-podman-rootless, ${{ matrix.runner }})
# Run directly on the Ubuntu host so the test observes the host's AppArmor
# and unprivileged-user-namespace policy. A privileged job container masks
# the restrictions that production rootless Podman installations enforce.
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
# Ubuntu 24.04 matches the environment reported in #2069 and ships
# Podman 4.x. The probe records whether AppArmor blocks the drop.
- runner: ubuntu-24.04
podman_major: "4"
# Ubuntu 26.04 provides the supported Podman 5.x coverage for
# comparison with the Ubuntu 24.04 environment.
- runner: ubuntu-26.04
podman_major: "5"
env:
IMAGE_TAG: ${{ inputs.image-tag }}
MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENSHELL_REGISTRY: ghcr.io/nvidia/openshell
OPENSHELL_REGISTRY_HOST: ghcr.io
OPENSHELL_REGISTRY_NAMESPACE: nvidia/openshell
OPENSHELL_REGISTRY_USERNAME: ${{ github.actor }}
OPENSHELL_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
OPENSHELL_SUPERVISOR_IMAGE: ${{ format('ghcr.io/nvidia/openshell/supervisor:{0}', inputs.image-tag) }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ inputs['checkout-ref'] || github.sha }}
persist-credentials: false

- name: Install mise
run: |
curl https://mise.run | MISE_VERSION=v2026.4.25 sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
echo "$HOME/.local/share/mise/shims" >> "$GITHUB_PATH"

- name: Install tools
run: mise install --locked

- name: Install Podman and build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential \
clang \
fuse-overlayfs \
libssl-dev \
libz3-dev \
openssh-client \
passt \
pkg-config \
podman \
slirp4netns \
uidmap

- name: Configure rootless Podman
run: |
if [ "${{ matrix.rootless }}" = "true" ]; then
TESTUID="$(id -u openshell-test)"
runuser -u openshell-test -- env \
XDG_RUNTIME_DIR="/run/user/${TESTUID}" \
HOME="/home/openshell-test" \
PATH="/usr/local/bin:/root/.cargo/bin:/opt/mise/shims:/root/.local/bin:${PATH}" \
CARGO_HOME="/home/openshell-test/.cargo" \
RUSTUP_HOME="/root/.rustup" \
MISE_DATA_DIR="/opt/mise" \
MISE_CACHE_DIR="/home/openshell-test/.cache/mise" \
MISE_STATE_DIR="/home/openshell-test/.local/state/mise" \
OPENSHELL_SUPERVISOR_IMAGE="${OPENSHELL_SUPERVISOR_IMAGE}" \
OPENSHELL_REGISTRY="${OPENSHELL_REGISTRY}" \
OPENSHELL_REGISTRY_HOST="${OPENSHELL_REGISTRY_HOST}" \
OPENSHELL_REGISTRY_USERNAME="${OPENSHELL_REGISTRY_USERNAME}" \
OPENSHELL_REGISTRY_PASSWORD="${OPENSHELL_REGISTRY_PASSWORD}" \
IMAGE_TAG="${IMAGE_TAG}" \
MISE_GITHUB_TOKEN="${MISE_GITHUB_TOKEN}" \
bash -c "${E2E_CMD}"
else
${E2E_CMD}
set -euo pipefail
if ! grep -q "^${USER}:" /etc/subuid; then
sudo usermod --add-subuids 100000-165535 "$USER"
fi
if ! grep -q "^${USER}:" /etc/subgid; then
sudo usermod --add-subgids 100000-165535 "$USER"
fi
runtime_dir="/run/user/$(id -u)"
sudo install -d -m 0700 -o "$(id -u)" -g "$(id -g)" "$runtime_dir"
echo "XDG_RUNTIME_DIR=$runtime_dir" >> "$GITHUB_ENV"

- name: Verify rootless Podman environment
run: |
set -euo pipefail
podman_version="$(podman version --format '{{.Client.Version}}')"
case "$podman_version" in
"${{ matrix.podman_major }}".*) ;;
*) echo "ERROR: expected Podman ${{ matrix.podman_major }}.x, found $podman_version" >&2; exit 1 ;;
esac
test "$(podman info --format '{{.Host.Security.Rootless}}')" = "true"
test "$(sudo sysctl -n kernel.apparmor_restrict_unprivileged_userns)" = "1"
echo "=== host ==="
uname -a
echo "=== AppArmor ==="
cat /proc/self/attr/current
sudo aa-status || true
echo "=== Podman ==="
podman version
podman info --debug

- name: Probe rootless capability bounding set
run: |
set -euo pipefail
probe="$RUNNER_TEMP/openshell-capbset-probe"
cc -static -O2 -Wall -Wextra -Werror \
e2e/support/capbset-probe.c \
-o "$probe"
podman run --rm \
--cap-add=SETPCAP \
--volume "$probe:/openshell-capbset-probe:ro" \
docker.io/library/alpine:3.22 \
/openshell-capbset-probe

- name: Log in to GHCR with Podman
run: echo "${{ secrets.GITHUB_TOKEN }}" | podman login ghcr.io -u "${{ github.actor }}" --password-stdin

- name: Run rootless Podman E2E
run: mise run --no-deps --skip-deps e2e:podman:rootless

- name: Print AppArmor denials
if: always()
run: sudo dmesg | grep -E 'apparmor=.*DENIED|profile="unprivileged_userns"' | tail -100 || true
2 changes: 1 addition & 1 deletion .github/workflows/release-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@ jobs:
cat release/openshell.rb

- name: Attest VM driver artifacts
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4
uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763 # v4
with:
subject-path: |
release/openshell-driver-vm-x86_64-unknown-linux-gnu.tar.gz
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ jobs:
cat release/openshell.rb

- name: Attest VM driver artifacts
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4
uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763 # v4
with:
subject-path: |
release/*.tar.gz
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-vm-kernel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ jobs:
merge-multiple: true

- name: Attest VM runtime artifacts
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4
uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763 # v4
with:
subject-path: |
release/vm-runtime-linux-aarch64.tar.zst
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ We use a vouch system. This exists because AI makes it trivial to generate plaus

### Finding Work

Issues labeled [`good-first-issue`](https://github.com/NVIDIA/OpenShell/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue) are scoped, well-documented, and friendly to new contributors. Start there. If you need guidance, comment on the issue.
Issues labeled [`good first issue`](https://github.com/NVIDIA/OpenShell/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) are scoped, well-documented, and friendly to new contributors. Start there. If you need guidance, comment on the issue.

All open issues are actionable — if it's in the issue tracker, it's ready to be worked on.

Expand Down
Loading
Loading