Sandbox host
sandbox.yaml says how this machine runs sandboxed tasks. Whether a task is sandboxed, and in which image, is set elsewhere: sandbox: in repos.yaml or a policy. The file is optional; a missing one is all defaults, which suit a machine with Docker and no SELinux.
cli: docker
selinux: auto
ca_bundle: /etc/ssl/corp-ca.pem
| Field | Default | Means |
|---|---|---|
cli | unset | docker or podman. Unset: docker when it is on PATH, otherwise podman. A docker that is Podman underneath (the podman-docker package) is recognised from its --version and treated as Podman. |
selinux | auto | What to do on a host where SELinux enforces, which denies every bind mount a container did not relabel. 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. 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 | An absolute path to a PEM file of extra root certificates a sandboxed task trusts, such as your TLS-intercepting proxy's CA. Unset: the daemon's SSL_CERT_FILE, when it has one and it is usable. One that cannot be used stops each sandboxed task. See CA certificates. |
relay_image | 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, with no network of its own, forwarding the worker's proxy port to Kraft; on Docker Desktop and Podman machine also 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 | {} | For a Kit's credentials: each credential@1 service mapped to the name of the daemon's own environment variable holding its value, as anthropic: KRAFT_ANTHROPIC_KEY. 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. |
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. |
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.
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 daemon'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 daemon'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, and SSL_CERT_FILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, GIT_SSL_CAINFO, NODE_EXTRA_CA_CERTS, CODEX_CA_CERTIFICATE, PIP_CERT and npm_config_cafile all name it. It 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 daemon 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 that cannot be read, is a directory, is not an absolute path or holds no PEM certificate stops each sandboxed task as a configuration error, and kraft admin doctor 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. When the container that reads the image's roots does not run (the pull failed or timed out, the image has no sh, the runtime did not answer), the task stops as a configuration error naming the image. 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 daemon'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 daemon's loopback (127.0.0.0/8, localhost, ::1) is left out: inside the container that address is the container itself, so forwarding it would fail every request, while 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 daemon's. They agree when both were started from the same shell; if the daemon 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 daemon makes the outbound connections through its own proxy, on its loopback or not.