agent-infra / agent-infra/sandbox

Support running the container as non-root (rootless) for hardened Kubernetes environments

Đang mở
#218 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Python
Star
5.9k
Fork
529
Merge trung bình
4 giờ 8 phút
Pull request đã merge (30 ngày)
4

Mô tả

## Problem

The image is root-first: `run.sh` → `gem_init.sh` → `gem.sh` run as **root**, performing `useradd`, `chown`, sudoers setup and `su - gem`, and then `supervisord` starts as root and drops each program to `user=gem`.

This makes the image unusable on platforms that **mandate** `runAsNonRoot` / a restricted PodSecurity or admission policy (e.g. GKE Autopilot's hardening policy, OpenShift's default SCC, any cluster enforcing `runAsNonRoot: true`). Starting the container as a non-root UID crashes immediately, e.g.:

```
mkdir: cannot create directory '/var/run/gem': Permission denied
mkdir: cannot create directory '/var/log/gem': Permission denied
```

and, further along, `supervisord: Error: Can't drop privilege as nonroot user`.

Tested on `ghcr.io/agent-infra/sandbox:1.10.0` and `1.11.0`.

## Request

First-class rootless support — ideally the bootstrap detects `euid != 0` and skips the privilege-management steps, with the runtime paths being user-writable/configurable, so downstreams don't have to patch the image.

## What we did to make it run as UID 1000 (as a reference workaround)

All applied in a downstream layer, without editing the large `gem.sh`:

1. **Pre-create + `chown` every runtime dir at build time** (`/var/run/gem`, `/var/log/gem`, `/var/log/nginx`, `/var/lib/aio-sandbox` + nginx temp dirs, `/tmp/.X11-unix`, `/run/user/`, `/etc/browser/policies/managed`, `/opt/gem`, `/opt/aio`, …), and ensure the user exists. `mkdir -p` on an existing dir is an idempotent no-op for non-root, and `chmod` works on owned dirs.
2. **PATH shims** so that, when already non-root, `chown` becomes a no-op and `su - -c CMD` runs `CMD` directly (delegating to the real binary when root).
3. **supervisord**: drop `user=root`, move the socket/pid file to a user-writable dir, and strip the per-program `user=` lines (supervisord can't `setuid` when non-root, even to the same user).
4. **nginx**: point `pid` at a user-writable path and add a main-context `error_log` (otherwise it falls back to the root-owned compile default `/var/log/nginx/error.log`).
5. **`browser-supervisor.py`**: skip the privilege drop (`initgroups`/`setgid`/`setuid`) and the pid-file `chown` when already running as the target uid — otherwise the `preexec_fn` raises `Operation not permitted` and Chromium never starts. Chromium also needs `--no-sandbox` under non-root (the existing `BROWSER_NO_SANDBOX` env covers this).

With the above, the container runs entirely as UID 1000 and all services (nginx gateway, opencode, jupyter, code-server, VNC, browser + CDP, mcp) come up healthy.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.