Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,17 @@
"enterprise/enterprise-vs-oss",
"enterprise/sizing-guide",
"enterprise/quick-start",
"enterprise/custom-sandbox-image",
{
"group": "Custom Sandbox Images",
"icon": "box",
"pages": [
"enterprise/custom-sandbox-images/index",
"enterprise/custom-sandbox-images/building-custom-images",
"enterprise/custom-sandbox-images/multiple-images-warm-pools",
"enterprise/custom-sandbox-images/single-image-admin-console",
"enterprise/custom-sandbox-images/using-custom-images"
]
},
"enterprise/docker-in-sandbox",
"enterprise/external-postgres",
"enterprise/troubleshooting"
Expand Down Expand Up @@ -881,6 +891,14 @@
{
"source": "/openhands/usage/automations/examples",
"destination": "/openhands/usage/automations/overview"
},
{
"source": "/enterprise/custom-sandbox-image",
"destination": "/enterprise/custom-sandbox-images"
},
{
"source": "/enterprise/custom-sandbox-image#run-multiple-custom-images-with-warm-runtime-pools",
"destination": "/enterprise/custom-sandbox-images/multiple-images-warm-pools"
}
]
}
}
482 changes: 0 additions & 482 deletions enterprise/custom-sandbox-image.mdx

This file was deleted.

110 changes: 110 additions & 0 deletions enterprise/custom-sandbox-images/building-custom-images.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
title: Building a Custom Sandbox Image
description: How to build, version, and push a custom sandbox image for use with OpenHands Enterprise.
icon: docker
---

All custom sandbox image approaches — single-image Admin Console and multi-image
warm runtime pools — start here. Build your image once and then point whichever
configuration approach you use at it.

## Basic Pattern

1. Start from the OpenHands agent-server base image.
2. Keep the normal OpenHands entrypoint intact: extend the image, do not replace it.
3. Add your repo, docs, tools, and verification wrappers.
4. Pre-run the expensive setup you do not want to repeat at task time.
5. Push the image to a registry reachable from your OpenHands cluster.

<Warning>
Do not override the entrypoint or replace the runtime contract of the base
image. OpenHands expects standard agent-server behavior. Only extend, do not
replace.
</Warning>

## Base Image

```dockerfile
FROM ghcr.io/openhands/agent-server:1.46.0-python
```

Pin a specific version tag to ensure reproducible builds, and replace it with
the tag expected by your installed release. See [Version Compatibility](#version-compatibility)
below to find the right tag.

## Version Compatibility

Each OpenHands Enterprise release expects a specific agent-server version. The
base image tag you build from must match the release you run: the
`openhands-sdk` inside the sandbox and the one inside the OpenHands application
must agree on major and minor version.

To find the expected tag for your release, enable **Use a Custom Sandbox
Image** in the Admin Console. The **Sandbox Image Tag** field defaults to the
tag the current release expects. Check
[ghcr.io/openhands/agent-server](https://github.com/OpenHands/OpenHands/pkgs/container/agent-server)
for available tags.

When a conversation starts on a custom image, OpenHands checks the sandbox's
agent-server version. If it does not match, the conversation fails with an
error naming the expected and actual versions. Rebuild your image from the
expected tag to fix it.

<Note>
Rebuild your custom image before each OHE upgrade. The agent-server base
image changes with every release, and an image built for an older release
will be rejected by the version check.
</Note>

## Build and Push

```bash
docker buildx build \
--platform linux/amd64 \
-f your-project/Dockerfile \
-t ghcr.io/<your-org>/openhands-custom-image:<your-tag> \
--push \
.
```

Use `--platform linux/amd64` because the Enterprise Replicated VM runs on x86-64.

## What to Bake In

Good candidates for prebaking:

Check warning on line 74 in enterprise/custom-sandbox-images/building-custom-images.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

enterprise/custom-sandbox-images/building-custom-images.mdx#L74

Did you really mean 'prebaking'?

- Pinned repository checkouts
- Package manager caches and installed dependencies (`node_modules`, Python virtualenvs, etc.)

Check warning on line 77 in enterprise/custom-sandbox-images/building-custom-images.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

enterprise/custom-sandbox-images/building-custom-images.mdx#L77

Did you really mean 'virtualenvs'?
- Compiled or transpiled output

Check warning on line 78 in enterprise/custom-sandbox-images/building-custom-images.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

enterprise/custom-sandbox-images/building-custom-images.mdx#L78

Did you really mean 'transpiled'?
- Native system packages (`xvfb`, `libkrb5-dev`, `pkg-config`, etc.)
- Browser or Electron artifacts
- Stable helper scripts such as `prepare-*` and `*-verify` wrappers

## What to Keep Out

<Warning>
Do not bake the following into your image:

- Secrets, API keys, or personal credentials
- Machine-specific paths or environment assumptions
- Uncommitted source changes or task-specific fixes
- Rapidly changing dependencies (use a lightweight `prepare-*` script instead)
</Warning>

If the repository or dependencies change frequently, include a `prepare-*`
script in the image so the agent can refresh only the parts that need updating
without a full rebuild.

## Private Registries

If your image lives in a private registry, provide pull credentials so the
cluster can fetch it at pod start time.

**Replicated VM installs:** set **Registry Server**, **Registry Username**, and
**Registry Password or Credentials** in **Config → Sandbox Configuration** in
the Admin Console and deploy. The installer renders an image pull secret that
runtime pods automatically use.

**Helm installs:** create a pull secret in the `openhands` namespace and add

Check warning on line 108 in enterprise/custom-sandbox-images/building-custom-images.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

enterprise/custom-sandbox-images/building-custom-images.mdx#L108

Did you really mean 'namespace'?
its name to the runtime-api `RUNTIME_IMAGE_PULL_SECRETS` environment variable
(comma-separated list of secret names).
83 changes: 83 additions & 0 deletions enterprise/custom-sandbox-images/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Custom Sandbox Images
description: Prebake your repository, dependencies, and tooling into custom sandbox images so agents start on the actual task instead of spending time on setup.
icon: box
---

Custom sandbox images let you prebake the repository, dependencies, compiled
output, and test harness your agents need. Instead of spending minutes
provisioning a workspace on every run, your agents start on the actual task
immediately.

## How Sandbox Pools Work

Each custom sandbox image can be kept ready in its own **pool** of
pre-started sandboxes (called warm runtime pools internally). When a user
starts a conversation, it claims a waiting sandbox from the pool in seconds
instead of cold-starting one from scratch (which takes 20 seconds or more).
Each configuration names one image and a pool size; a reconciler runs every
minute to maintain that count. Multiple pools run side by side, each
independently selectable by users.

## Prerequisites

Before configuring any custom image, the following must be in place:

**An image registry reachable from your OpenHands cluster.** The cluster must
be able to pull your custom image at pod start time. Public registries (GitHub
Container Registry, Docker Hub) work without extra configuration. Private
registries require credentials — either set via **Config → Sandbox
Configuration → Registry Server / Username / Password** in the Admin Console,
or via the `RUNTIME_IMAGE_PULL_SECRETS` setting on Helm installs.

**A custom image built from the correct agent-server base.** See
[Building a Custom Image](/enterprise/custom-sandbox-images/building-custom-images).
The image must be pushed to your registry before you configure it.

**OpenHands Enterprise 0.64.0 or later** for the warm runtime pool approach.

**`kubectl` access** for initial setup, with different requirements by install type:

- **Replicated VM installs:** kubectl is needed once to read the initial
credentials. After that the management script calls the runtime-api HTTPS
endpoint directly and can run from any machine without cluster access.
- **Helm installs:** kubectl is required for every management operation.
Use your normal kubeconfig.

Check warning on line 45 in enterprise/custom-sandbox-images/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

enterprise/custom-sandbox-images/index.mdx#L45

Did you really mean 'kubeconfig'?

## Configuration Approaches

<CardGroup cols={2}>
<Card
title="Configuring Custom Sandbox Images"
icon="layer-group"
href="/enterprise/custom-sandbox-images/multiple-images-warm-pools"
>
One warm pool per image, selectable per user. Changes take effect within a
minute with no restarts. **Recommended.**
</Card>
<Card
title="Single Image via Admin Console"
icon="triangle-exclamation"
href="/enterprise/custom-sandbox-images/single-image-admin-console"
>
**Deprecated.** Configures one image for the whole installation via the
Replicated Admin Console. Superseded by the warm runtime pool approach.
</Card>
</CardGroup>

## Reference

<CardGroup cols={2}>
<Card title="Building a Custom Image" icon="docker" href="/enterprise/custom-sandbox-images/building-custom-images">
Dockerfile pattern, version pinning, and what to bake in
</Card>
<Card title="Using Custom Images" icon="play" href="/enterprise/custom-sandbox-images/using-custom-images">
How users select an image and how to target one via the API
</Card>
<Card title="Conversations and Sandboxes" icon="comments" href="/enterprise/conversations-and-sandboxes">
How conversations, sandboxes, and their lifecycle fit together
</Card>
<Card title="Sizing Guide" icon="gauge-high" href="/enterprise/sizing-guide">
Capacity planning, including headroom for warm pools
</Card>
</CardGroup>
Loading
Loading