sandbox.yaml
sandbox.yaml says how this machine runs sandboxed tasks: the container CLI, SELinux, an extra CA and the proxy. Whether a task is sandboxed, and in which image, is set elsewhere: sandbox: in repos.yaml or a policy.
cli: docker
selinux: auto
ca_bundle: /etc/ssl/corp-ca.pem
The file is optional. A missing one is all defaults, which suit a machine with Docker and no SELinux.
| Field | Type | Default | Meaning |
|---|---|---|---|
cli | docker or podman | unset | The container CLI. Unset: docker when it is on PATH, otherwise podman. A docker that is Podman underneath (the podman-docker package) is recognized from its --version and treated as Podman. |
selinux | relabel, disable or auto | auto | What to do on a host where SELinux enforces, which denies every bind mount a container did not relabel. See selinux. |
ca_bundle | string, an absolute path | unset | A PEM file of extra root certificates a sandboxed task trusts, such as your TLS-intercepting proxy's CA. See ca_bundle and CA certificates. |
relay_image | string, an image reference | docker.io/alpine/socat@sha256:5ffbd6ae… (socat 1.8.1.3, pinned by digest) | The image of the relay container a sandboxed session under a network policy runs beside its worker. See relay_image. |
credentials | mapping of string to string | {} | For a Kit's credentials: each credential@1 service mapped to the name of the server's own environment variable holding its value, as anthropic: KRAFT_ANTHROPIC_KEY. See credentials. |
Field details
selinux
On a host where SELinux enforces, every bind mount a container did not relabel is denied. The three values:
| Value | What it does |
|---|---|
relabel | Adds the shared z label to each mount, which relabels the worktree and your repository's files for containers once. |
disable | Runs Kraft's containers with --security-opt label=disable, leaving the files alone and SELinux separation off for those containers only. |
auto | Stops each sandboxed task as a configuration error that names both, because either one changes something outside Kraft. |
selinux is ignored where SELinux is off or permissive, and where the runtime applies no labels (Docker does only when its daemon runs with SELinux support), since its mounts then work as they are.
ca_bundle
Unset: the server's SSL_CERT_FILE, when it has one and it is usable. One that cannot be used stops each sandboxed task.
relay_image
The relay container has no network of its own and forwards the worker's proxy port to Kraft. On Docker Desktop and Podman machine it is also the image of the second relay of each session.
Set it to use a mirror or your own socat image. kraft admin doctor fails when it is not pulled; pull it before filing work.
credentials
A Kit never picks a host variable itself, and its credential is read from nothing else. A required credential with no binding stops each item under the Kit, naming the binding to add. An optional one is skipped, and kraft admin doctor warns about it.
Container user
Kraft asks the runtime whether it is rootless, and runs the container so that what the worker writes stays yours:
| Runtime | Runs the container as |
|---|---|
| Docker | Your uid and gid. |
| Rootless Docker | Container root, which rootless Docker maps to you. Any other uid would land in your subordinate range, and you could not edit what it wrote. Capabilities stay dropped. |
| Podman | Your uid and gid. |
| Rootless Podman | Your uid and gid, with --userns=keep-id: without it your uid does not exist in the container, and the worktree is not writable. |
A runtime that does not answer
A runtime that does not answer is never taken for a rootful one: a launch that gets no answer stops as a configuration error that says so. kraft admin doctor asks the same way, once per run however many repositories are sandboxed. It says when it is waiting for the second answer, and it can take about a minute when the runtime does not answer.
The timings and the threads behind that, all in one place:
- Its
infocan be slow: a rootless Podman's first one on a busy host has taken over ten seconds, Kraft's first wait. - After that, the next launch asks once more and waits up to 30 seconds. Any launch that starts meanwhile waits for that answer.
- If there is still no answer, the launch stops. Launches in the 30 seconds after that stop the same way without asking, and then Kraft asks again.
- A launch asks these questions from a worker thread. The rest of Kraft reads the last answer, and a question that is due again is asked in the background, so the server never stalls waiting for one.
- An answer Kraft already has is kept: a later ask that gets none does not replace it.
- The one exception is rootless Docker, whose container root would be real root if Docker's daemon has since become rootful. The next launch asks again, as above, and stops if there is still no answer.
To see how long your runtime takes, run time podman info (or time docker info), then kraft admin doctor.
Ownership and limits
On a rootless runtime, a task stops as a configuration error before it starts if the work item's sandbox HOME, its ref store or its result file belongs to another user, as one can after switching runtimes. The message names the path: chown it back to yourself, or remove it.
A workspace item has one ref store for each repository, its members' and its root's, and each is checked the same way.
Kraft also asks the runtime which resource limits it can enforce: a task that sets one it cannot stops as a configuration error rather than running without it.
When the file is read
Kraft reads the file and asks the runtime once, at the first sandboxed launch after it starts. kraft admin doctor reads both again, so run it after editing the file. Restart Kraft for running tasks to pick the change up.
CA certificates
A container does not have the files the server's SSL_CERT_FILE or ca_bundle name, so Kraft never forwards those paths. When there is an extra CA, ca_bundle or else the server's SSL_CERT_FILE, Kraft builds one bundle per image under $KRAFT_HOME/run/sandbox-ca/:
- the image's own roots, read once per image id by a container with no network, from the first of
/etc/ssl/certs/ca-certificates.crt,/etc/pki/tls/certs/ca-bundle.crtand/etc/ssl/cert.pemit holds (none: the extra CA alone); - then every certificate in the extra CA.
The bundle is mounted read-only at /etc/kraft/ca-bundle.pem, for sessions and the setup command alike. These variables all name it:
SSL_CERT_FILEREQUESTS_CA_BUNDLECURL_CA_BUNDLEGIT_SSL_CAINFONODE_EXTRA_CA_CERTSCODEX_CA_CERTIFICATEPIP_CERTnpm_config_cafile
The bundle holds the image's roots too, because most of those variables replace a tool's store rather than add to it. A repository's own env still wins over any of them.
The extra CA is read at every launch, so an edit to ca_bundle or to the file needs no restart. With no extra CA, no bundle is built and nothing is mounted or set.
SSL_CERT_FILE counts
When ca_bundle is unset and the server has SSL_CERT_FILE, that file is the extra CA, so every sandboxed launch on such a host builds and mounts a bundle. Set ca_bundle to choose a different file.
An unusable CA
A ca_bundle stops every sandboxed task as a configuration error when it:
- cannot be read
- is a directory
- is not an absolute path
- holds no PEM certificate
kraft admin doctor also fails the repository's sandbox row: you named it for sandboxes, so it is never skipped.
An unusable SSL_CERT_FILE is ignored instead, since it was not set for sandboxes. Tasks launch as they would without it, and doctor shows a ca warning saying why it was not used.
An image whose roots cannot be read
The container that reads the image's roots may not run: the pull failed or timed out, the image has no sh, or the runtime did not answer. The task then stops as a configuration error naming the image, because a bundle of the extra CA alone would replace the store and fail TLS to every other host. Nothing is cached, so the next launch tries again.
Proxy
The server's proxy variables (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY, in either case) reach a sandboxed task by name, so a proxy password never appears on the docker command line.
A proxy on the server's loopback is left out. That means 127.0.0.0/8, ::1, localhost or any *.localhost name, or the unspecified address 0.0.0.0 or ::. Inside the container that address is the container itself, so forwarding it would fail every request. Leaving it out at least lets the task go direct where the host allows that.
kraft admin doctor warns about such a proxy for each sandboxed repository.
Doctor's proxy and CA checks read the environment of the kraft admin doctor process itself, not the running server's. They agree when both were started from the same shell. If the server runs as a service with its own environment, check that environment instead.
Under a sandbox network policy none of these variables is forwarded, and doctor does not warn. The container's only proxy is Kraft's own, and the server makes the outbound connections through its own proxy, on its loopback or not.
Related
- Sandboxed workers: what else reaches the container, and the
sandboxkey. - Network policy: the relay
relay_imageruns, and the proxy a policy replaces. - Environment variables:
SSL_CERT_FILEamong the variables Kraft reads.