Skip to content

Commit f1ed347

Browse files
authored
fix(driver-podman): bind gateway to 0.0.0.0 in rootless mode (#1623)
Rootless Podman sandbox containers reach the host through pasta's local connection bypass, which translates L2 frames to L4 host sockets. The dev gateway script binds to 127.0.0.1 by default, which is not routable through pasta. Auto-detect rootless mode and bind to 0.0.0.0 so sandbox containers can connect to the gateway. - Auto-detect rootless Podman in gateway.sh and export OPENSHELL_BIND_ADDRESS=0.0.0.0 when not explicitly set - Add e2e:podman:rootless mise task and CI matrix entry to validate rootless Podman networking end-to-end - CI creates a non-root user inside the privileged container to trigger Podman's rootless code paths (pasta, user namespace isolation) Signed-off-by: Naveen Malik <nmalik@redhat.com>
1 parent 7d32bf9 commit f1ed347

4 files changed

Lines changed: 71 additions & 2 deletions

File tree

.github/workflows/e2e-test.yml

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ jobs:
4040
- suite: rust-podman
4141
cmd: "mise run --no-deps --skip-deps e2e:podman"
4242
apt_packages: "openssh-client podman"
43+
- suite: rust-podman-rootless
44+
cmd: "mise run --no-deps --skip-deps e2e:podman:rootless"
45+
apt_packages: "openssh-client podman uidmap"
46+
rootless: true
4347
container:
4448
image: ghcr.io/nvidia/openshell/ci:latest
4549
credentials:
@@ -72,14 +76,48 @@ jobs:
7276
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
7377

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

82+
- name: Set up rootless Podman user
83+
if: matrix.rootless
84+
run: |
85+
useradd -m openshell-test
86+
echo "openshell-test:100000:65536" >> /etc/subuid
87+
echo "openshell-test:100000:65536" >> /etc/subgid
88+
mkdir -p "/run/user/$(id -u openshell-test)"
89+
chown openshell-test: "/run/user/$(id -u openshell-test)"
90+
chmod 700 "/run/user/$(id -u openshell-test)"
91+
chown -R openshell-test: .
92+
for dir in /root/.cargo /root/.rustup /root/.local/share/mise /opt/mise; do
93+
[ -d "$dir" ] && chmod -R a+rX "$dir"
94+
done
95+
7896
- name: Install Python dependencies and generate protobuf stubs
7997
if: matrix.suite == 'python'
8098
run: uv sync --frozen && mise run --no-deps python:proto
8199

82100
- name: Run tests
83101
env:
84102
OPENSHELL_SUPERVISOR_IMAGE: ${{ format('ghcr.io/nvidia/openshell/supervisor:{0}', inputs.image-tag) }}
85-
run: ${{ matrix.cmd }}
103+
E2E_CMD: ${{ matrix.cmd }}
104+
run: |
105+
if [ "${{ matrix.rootless }}" = "true" ]; then
106+
TESTUID="$(id -u openshell-test)"
107+
runuser -u openshell-test -- env \
108+
XDG_RUNTIME_DIR="/run/user/${TESTUID}" \
109+
HOME="/home/openshell-test" \
110+
PATH="/root/.cargo/bin:/opt/mise/shims:/opt/mise/bin:${PATH}" \
111+
CARGO_HOME="/root/.cargo" \
112+
RUSTUP_HOME="/root/.rustup" \
113+
OPENSHELL_SUPERVISOR_IMAGE="${OPENSHELL_SUPERVISOR_IMAGE}" \
114+
OPENSHELL_REGISTRY="${OPENSHELL_REGISTRY}" \
115+
OPENSHELL_REGISTRY_HOST="${OPENSHELL_REGISTRY_HOST}" \
116+
OPENSHELL_REGISTRY_USERNAME="${OPENSHELL_REGISTRY_USERNAME}" \
117+
OPENSHELL_REGISTRY_PASSWORD="${OPENSHELL_REGISTRY_PASSWORD}" \
118+
IMAGE_TAG="${IMAGE_TAG}" \
119+
MISE_GITHUB_TOKEN="${MISE_GITHUB_TOKEN}" \
120+
bash -c "${E2E_CMD}"
121+
else
122+
${E2E_CMD}
123+
fi

e2e/rust/e2e-podman-rootless.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# Run the Podman e2e suite and verify rootless mode.
6+
#
7+
# Identical to e2e-podman.sh but fails fast if Podman is not running
8+
# rootless. Use this to explicitly validate the rootless networking
9+
# path (pasta, host-gateway, bind address).
10+
11+
set -euo pipefail
12+
13+
if podman info --format '{{.Host.Security.Rootless}}' 2>/dev/null | grep -q false; then
14+
echo "ERROR: podman is not running rootless; this test requires rootless mode" >&2
15+
exit 2
16+
fi
17+
18+
exec "$(dirname "${BASH_SOURCE[0]}")/e2e-podman.sh"

tasks/scripts/gateway.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,15 @@ if [[ "${DRIVER}" == "podman" ]]; then
271271
SUPERVISOR_IMAGE="${OPENSHELL_SUPERVISOR_IMAGE:-openshell/supervisor:dev}"
272272
ensure_podman_supervisor_image "${SUPERVISOR_IMAGE}"
273273
export OPENSHELL_SUPERVISOR_IMAGE="${SUPERVISOR_IMAGE}"
274+
275+
# Rootless Podman containers reach the host via pasta's local connection
276+
# bypass, which translates to host L4 sockets. The gateway must listen on
277+
# 0.0.0.0 so pasta can reach it — 127.0.0.1 is not routable through pasta.
278+
if [[ -z "${OPENSHELL_BIND_ADDRESS:-}" ]]; then
279+
if podman info --format '{{.Host.Security.Rootless}}' 2>/dev/null | grep -q true; then
280+
export OPENSHELL_BIND_ADDRESS="0.0.0.0"
281+
fi
282+
fi
274283
fi
275284

276285
if [[ ! "${GATEWAY_NAME}" =~ ^[A-Za-z0-9._-]+$ ]]; then

tasks/test.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ run = "e2e/with-docker-gateway.sh uv run pytest -o python_files='test_*.py' -m g
7171
description = "Run Rust CLI e2e tests against a Podman-backed gateway"
7272
run = "e2e/rust/e2e-podman.sh"
7373

74+
["e2e:podman:rootless"]
75+
description = "Run Rust CLI e2e tests against a rootless Podman-backed gateway"
76+
run = "e2e/rust/e2e-podman-rootless.sh"
77+
7478
["e2e:podman:gpu"]
7579
description = "Run GPU e2e against a standalone gateway with the Podman compute driver"
7680
env = { OPENSHELL_E2E_PODMAN_GPU = "1", OPENSHELL_E2E_PODMAN_TEST = "gpu_device_selection", OPENSHELL_E2E_PODMAN_FEATURES = "e2e-podman-gpu" }

0 commit comments

Comments
 (0)