Sandboxes
A sandbox is the Docker container a run executes in, and you choose what goes into it and what it can reach. You set it up in the job’s Environment tab and in the Sandbox and Secrets cards of its Settings tab.
One container per run
Section titled “One container per run”Umpteenth starts a fresh container for each run and executes the agent’s commands and the playbook’s scripts in it as the user agent (uid 1000), with all Linux capabilities dropped.
The job’s stdio MCP servers run there too.
Once the run ends, Umpteenth collects the files in /ump/outputs as the run’s artifacts and removes the container, along with anything else the run left in it, such as a package the agent installed or a file in /workspace.
Each sandbox gets 1 CPU and 1024 MB of memory by default, which you change in the job’s Sandbox card or under Settings → General → Sandbox defaults (Managing jobs).
The default image
Section titled “The default image”Runs use ghcr.io/stonith404/umpteenth-sandbox:latest, a Debian trixie-slim image with bash, coreutils, curl, git, jq, ripgrep, python3 with pip and requests, uv, node and npm.
To start from another image, set Default image under Settings → General → Sandbox defaults for the workspace, or Base image in a job’s Sandbox card for that job alone.
A custom image needs bash and an amd64 or arm64 build, because Umpteenth runs commands with bash -lc and ships its ump CLI for those two architectures.
Umpteenth pulls an image only if the Docker host lacks it, so after you push a new version under the same tag, run docker pull on the host.
A Dockerfile per job
Section titled “A Dockerfile per job”If a job needs a Python package such as pandas and has no Dockerfile, the agent installs it on every run, and you pay for those turns each time.
Put it in the job’s Dockerfile instead: Umpteenth installs it once, when it builds the image, and the install drops off your model bill.
System packages such as ffmpeg belong there too, since the agent can’t install them without root.
Open the job’s Environment tab, click Add a Dockerfile, which fills in a template, and add what the job needs:
FROM ghcr.io/stonith404/umpteenth-sandbox:latestRUN apt-get update && apt-get install -y --no-install-recommends ffmpeg && rm -rf /var/lib/apt/lists/*RUN uv pip install --system pandasClick Save & build, and Umpteenth saves the Dockerfile as a new playbook version and builds the image.
A run that starts before the image is ready waits for it, and the wait counts against the run’s Timeout.
From then on the Dockerfile’s FROM line sets the job’s image, and the Base image field no longer applies.
Umpteenth builds the image under these rules:
- The build gets the Dockerfile alone, with no build context, so
COPYof local files fails. - Umpteenth uses Docker’s classic builder, which rejects BuildKit syntax such as
RUN --mountand heredocs. - Registry validation, base-image resolution and the build share a 15-minute deadline, and the completed image can be up to 5 GiB.
- Docker build steps get 1 CPU and 1 GiB of memory, including swap. These limits apply to builds separately from the job’s run limits. Docker’s classic build API provides no process-count or writable-storage limit, so use a dedicated builder host with bounded storage for untrusted builds.
- Build steps reach the internet through the egress proxy, whatever the job’s network setting.
ADD, custom Dockerfile frontends,RUNmounts with afromsource and deferredONBUILDcopies or mounts with source flags fail validation. Download files withcurlin aRUNstep instead.- While
network.allow_private_targetsisfalse, images on a registry at a private address fail the build too, unless they come fromsandbox.registry.repository. On the configured registry host, a job can reference only its own images or the operator-selectedsandbox.image; this rule also applies to the job’s Base image. Docker downloads other images through Umpteenth’s outbound guard, including registry redirects and authentication endpoints.
The compile step and reflection write Dockerfiles as well. The Sandbox card on the New job review screen has a Custom environment switch, which the compile step turns on if it proposes a Dockerfile, and Umpteenth builds that image before the first run. With Self-improve on, reflection moves packages the agent installed by hand into the Dockerfile after a run (How jobs learn).
Builds and base image updates
Section titled “Builds and base image updates”Umpteenth builds each Dockerfile once and reuses the image for every run until the Dockerfile changes. Log in the Builds list below the editor opens a build’s output, live while the build runs.
Each build pulls the FROM image, so click Rebuild after a new version of the base image comes out, for example after you upgrade Umpteenth.
Runs keep using the last good build of the Dockerfile while a rebuild runs, and if it fails.
A failed build blocks runs
Section titled “A failed build blocks runs”If a Dockerfile has no successful build and its latest build failed, every run of the job fails with Environment build failed: <error>.
Read the build’s Log, fix the Dockerfile and click Save & build.
Click Rebuild instead if the cause lay outside the Dockerfile, such as a package mirror that was down.
To run the job on its base image again, click Use the base image, which removes the Dockerfile and keeps it in the playbook’s history for a rollback.
Run as root
Section titled “Run as root”Run as root in the Sandbox card runs the agent’s commands and the playbook’s scripts as root with Docker’s default capabilities, so the agent can install system packages during a run. Those packages disappear with the sandbox, and the agent installs them again next time, so a package the job always needs belongs in its Dockerfile. A root sandbox skips stdio MCP servers that have environment variables, since root could read them (MCP servers).
Network
Section titled “Network”The Network select in the Sandbox card has four options: Internet access, Allowed domains only, No network and, if the instance offers it, Unrestricted network.
The New job page offers only Internet access and No network, so switch to another option in the job’s settings after you save it.
ump calls and HTTP MCP servers work with every option, because Umpteenth makes those connections on the sandbox’s behalf.
Internet access
Section titled “Internet access”Internet access is the default. The sandbox reaches the internet only through Umpteenth’s egress proxy, which connects to any public address and refuses private networks, the Docker host and cloud metadata (Security).
Umpteenth sets HTTP_PROXY, HTTPS_PROXY and ALL_PROXY in the sandbox, and most tools pick them up, from curl and git to pip, uv and npm.
SSH, and with it git over SSH, goes through the proxy with ump connect.
The sandbox can’t resolve public names itself, so tools that ignore the proxy variables can’t connect: ping, anything over UDP, TCP clients without SOCKS support and Java without proxy flags.
Give a job that needs one of those the Unrestricted network.
The run’s timeline shows the first connection to each host and every refusal as a ump proxy <host> step.
Allowed domains only
Section titled “Allowed domains only”Pick Allowed domains only for a job that needs a few known hosts and nothing else. The egress proxy then connects only to the hosts you list under Allowed domains, one per line:
api.github.com*.githubusercontent.com*.example.com matches every name below example.com but not example.com itself, so list both if a job needs both.
Any port on an allowed host works, so github.com on the list lets git reach it over SSH too.
A connection to a host off the list fails with <host> is not on this job's allow-list and leaves a red ump proxy <host> step on the timeline, where you read the name to add.
Job settings lists the rules for the field.
No network
Section titled “No network”The sandbox is offline, but ump commands and HTTP MCP servers keep working.
A job that talks to other services through HTTP MCP servers alone runs fine this way.
A stdio MCP server started with npx -y can’t download its package here, so install it in the job’s Dockerfile (MCP servers).
Unrestricted network
Section titled “Unrestricted network”Unrestricted network turns the network sandboxing off.
The sandbox gets a direct route out and reaches everything the host can, your LAN, the Docker host and cloud metadata included.
It suits a job whose tools ignore proxy settings, as long as you trust its instruction and the content it reads.
The option appears while sandbox.allow_unrestricted_network is on, which it is by default (Security).
Allow private network
Section titled “Allow private network”Turn on Allow private network for a job that needs your LAN or the Docker host, such as a Gitea instance on your home network. The switch appears for Internet access and Allowed domains only. It lets the egress proxy connect to private addresses, while loopback addresses and cloud metadata stay blocked (Security).
Secrets
Section titled “Secrets”Create a secret for each credential under Settings → Secrets with Create secret. Umpteenth encrypts the values at rest, and neither the UI nor the API shows a value again.
A secret reaches a run only after you map it in the job’s Secrets card: click Add secret, pick the secret and name the environment variable.
Umpteenth reads the values when each run starts, so an updated secret applies from the next run.
The variables exist for every command in the sandbox, from the agent’s shell to the playbook’s scripts.
On the New job review screen, the Secrets card lists the variables the compile step found in your instruction, with the secret that holds each one already picked.
A variable without a match shows Pick a secret.
Create the secret in another tab, and the card picks it once you come back if its name matches the variable, as github-token matches GITHUB_TOKEN.
Saving the job maps the picked secrets.
The agent gets no list of the variables, so name them in the instruction:
Fetch the open pull requests of acme/api from the GitHub API with curl, using $GITHUB_TOKEN as the bearer token.Deleting a secret removes it from every job that maps it.
MCP servers take secrets as {{secret:NAME}} in their headers and environment instead, as MCP servers shows.
Files and paths
Section titled “Files and paths”| Path | Contents |
|---|---|
/workspace |
The working directory of the agent’s commands and the playbook’s scripts |
/ump/input.json |
The run’s input: a webhook body, the Input of Run now or the API, or {} |
/ump/outputs/ |
Files to keep, which Umpteenth collects as the run’s artifacts, up to 50 MiB, even from a failed run |
/ump/PLAYBOOK.md |
The job’s current playbook as Markdown |
/ump/skills/<name>/ |
The job’s skills, owned by root |
You download artifacts from the run’s Outputs tab (Reading a run), and the ump CLI reference lists the other paths.