docs(daytona): document operator enablement for the advisory bwrap wrapper (#10560)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Daytona sandbox provider now uses an advisory bwrap wrapper > - Operators need clear host and image setup for bubblewrap, sudo, and user namespaces > - The repo should document that setup, but it should not own provisioning > - This pull request adds the operator guidance to the shared sandbox requirements and the Daytona README > - The benefit is that operators can enable the wrapper with the same steps the code expects ## Linked Issues or Issue Description Refs #10554 and #10541. ## What Changed - Added an advisory bwrap prerequisites section to `packages/plugins/sandbox-providers/SANDBOX-REQUIREMENTS.md`. - Added an operator enablement section to `packages/plugins/sandbox-providers/daytona/README.md`. - Documented the install commands, the sudoers rule, the user namespace setting, and the verification command. - Kept provisioning out of the repo and left it to the image or snapshot layer. ## Verification - `git diff --check origin/master...HEAD` - `gh pr checks 10560` ## Risks - Low risk. This change updates documentation only. - The docs can drift if the host setup changes later. - Provisioning still lives outside the repo. ## Model Used - OpenAI Codex, GPT-5, tool use enabled. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used with version and capability details - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either linked existing issues with `Fixes: #` / `Closes: #` / `Refs #` OR described the issue in-PR following the relevant issue template - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
51bb41c7e3
commit
c4f62644b0
|
|
@ -6,6 +6,32 @@ exec time. The environment is a requirement, not a build step.
|
|||
|
||||
This document states requirements. It does not state build steps.
|
||||
|
||||
## bwrap prerequisites (advisory, optional)
|
||||
|
||||
A sandbox provider can wrap a command with an advisory bubblewrap (`bwrap`)
|
||||
wrapper. The wrapper is advisory, best-effort, and automatic. It adds no
|
||||
security. The ephemeral sandbox model stays the only security posture. A missing
|
||||
prerequisite degrades to the plain command. It never fails the lease. Daytona is
|
||||
the current provider with bwrap support.
|
||||
|
||||
The wrapper needs three run-time prerequisites. Each prerequisite is a fact of
|
||||
the image or snapshot, not a fact of the runtime code. The runtime does not
|
||||
build the image or snapshot. The runtime only probes for the capability and
|
||||
degrades when the capability is absent. So each prerequisite is an owner
|
||||
responsibility under the requirement-not-build contract above:
|
||||
|
||||
- The `bubblewrap` package is installed, and the `bwrap` binary is on the PATH
|
||||
(normally `/usr/bin/bwrap`).
|
||||
- A passwordless `sudo` rule lets the sandbox user run `bwrap` as root.
|
||||
- The host and kernel allow an unprivileged user namespace.
|
||||
|
||||
The owner supplies these prerequisites through the image or snapshot. The
|
||||
provider README states the distro-specific install commands, the exact sudoers
|
||||
rule, the user-namespace setting, and the verification command. The install and
|
||||
the sudoers change are environment provisioning at the image or snapshot layer.
|
||||
Route them to DevOps through the board. Do not add a provisioning script to the
|
||||
repository.
|
||||
|
||||
## Required on PATH
|
||||
|
||||
- `node` must be installed and on the PATH.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,93 @@ The driver wraps a sandbox command with an advisory bubblewrap (`bwrap`) wrapper
|
|||
- **The writable set is the workspace plus the read-write sync destinations.** The wrapper binds the workspace directory read-write as the baseline; the workspace is always durable. It adds the read-write sync destinations that a sync-in recorded for the same lease. The set deduplicates the directories. The baseline keeps a safe result even when the collected set is empty.
|
||||
- **The wrapper runs at execute time when the capability is present.** The driver wraps the command only when the lease reports `bwrapAvailable: true` and a uid/gid pair is known. It binds the workspace and the read-write sync destinations, keeps the root read-only for feedback, and re-binds the stdin file after the fresh `/tmp`. It runs the plain command when the capability or the uid/gid is missing. A wrap without a uid/gid would run as root and give the agent's files root ownership, so the driver keeps the plain command in that case.
|
||||
|
||||
## Operator enablement (advisory bwrap)
|
||||
|
||||
The advisory `bwrap` wrapper needs three run-time prerequisites on the image or
|
||||
snapshot. The repository does not build the Daytona image or snapshot. It
|
||||
references an external `image` or `snapshot`. So the three prerequisites are
|
||||
image facts, not code facts. The runtime only probes for the capability and
|
||||
degrades when the capability is absent.
|
||||
|
||||
The wrapper is advisory, best-effort, and automatic. It adds no security. The
|
||||
ephemeral sandbox model stays the only security posture. A missing prerequisite
|
||||
degrades to the plain command. It never fails the lease. So the enablement below
|
||||
is optional. It gives the agent real-time feedback on a non-durable write. It
|
||||
does not change the security posture.
|
||||
|
||||
The install and the sudoers change are environment provisioning at the image or
|
||||
snapshot layer. Route them to DevOps through the board. Do not run the steps
|
||||
from the runtime and do not commit a provisioning script to the repository.
|
||||
|
||||
### 1. Install the `bubblewrap` package
|
||||
|
||||
The repository does not state the Daytona base distribution. Confirm the
|
||||
distribution on the referenced image or snapshot first, then run the matching
|
||||
command:
|
||||
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
apt-get install -y bubblewrap
|
||||
# Alpine
|
||||
apk add bubblewrap
|
||||
# Fedora/RHEL
|
||||
dnf install -y bubblewrap
|
||||
```
|
||||
|
||||
Confirm the binary path is `/usr/bin/bwrap` after the install.
|
||||
|
||||
### 2. Add the passwordless sudoers rule
|
||||
|
||||
The wrapper runs `bwrap` as root with `sudo -n`. Add this exact sudoers line.
|
||||
Use the real sandbox user name and the real `bwrap` path:
|
||||
|
||||
```text
|
||||
<sandbox-user> ALL=(root) NOPASSWD: /usr/bin/bwrap
|
||||
```
|
||||
|
||||
The `<sandbox-user>` is the account name that `id -un` returns inside the
|
||||
sandbox. Use the account name, not a numeric id, in the sudoers line. The probe
|
||||
reads the numeric user id and group id with `id -u` and `id -g`. The driver
|
||||
resolves the sandbox work directory first, then the user home directory. It uses
|
||||
`/home/daytona` only as a fallback default when both are empty. Confirm the real
|
||||
home directory for your image or snapshot. Install the `sudo` package in the
|
||||
image or snapshot if it is absent.
|
||||
|
||||
### 3. Allow user namespaces
|
||||
|
||||
The `bwrap` wrapper creates a user namespace. The kernel must support user
|
||||
namespaces for the wrapper to run. Confirm the kernel allows them:
|
||||
|
||||
```bash
|
||||
sysctl user.max_user_namespaces
|
||||
```
|
||||
|
||||
A value greater than zero means the kernel supports user namespaces. This value
|
||||
is the requirement for the wrapper.
|
||||
|
||||
The wrapper runs `bwrap` as root with `sudo -n`. Root creates the user namespace
|
||||
directly, so the Debian/Ubuntu `kernel.unprivileged_userns_clone` setting does
|
||||
not apply here. That setting only limits an unprivileged process. A managed
|
||||
sandbox that denies `sysctl kernel.unprivileged_userns_clone=1` still runs the
|
||||
wrapper when `user.max_user_namespaces` is greater than zero.
|
||||
|
||||
### 4. Verify the three prerequisites
|
||||
|
||||
Run this exact command as the sandbox user:
|
||||
|
||||
```bash
|
||||
sudo -n bwrap --unshare-user --uid 0 --gid 0 --ro-bind / / -- true
|
||||
```
|
||||
|
||||
A zero exit code means all three prerequisites are met. A non-zero exit code
|
||||
means one prerequisite is missing. The wrapper then stays off and runs the plain
|
||||
command.
|
||||
|
||||
The `--uid 0` and `--gid 0` flags map the check to root inside the test
|
||||
namespace. This command is only a capability check. It does not need to match
|
||||
the sandbox user id. The live wrapper maps to the real sandbox user id and group
|
||||
id.
|
||||
|
||||
## Local development
|
||||
|
||||
```bash
|
||||
|
|
|
|||
Loading…
Reference in New Issue