> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openhands.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Amazon EKS

> Prepare an Amazon EKS cluster to run OpenHands Enterprise

Running OpenHands Enterprise on Amazon EKS follows the standard
[Helm install](/enterprise/k8s-install/installation), with a few EKS-specific choices for node
pools, storage, ingress, and the sandbox runtime. This guide covers preparing the cluster. Once
it's ready, follow the Helm install to deploy.

## Cluster Requirements

| Requirement   | Recommendation                                                                                               |
| ------------- | ------------------------------------------------------------------------------------------------------------ |
| EKS version   | A currently-supported version that [Sysbox](/enterprise/k8s-install/sysbox) supports                         |
| Add-ons       | VPC CNI, CoreDNS, kube-proxy, and the **EBS CSI driver** (sandboxes and stateful components use EBS volumes) |
| Storage class | A `gp3` StorageClass backed by the EBS CSI driver                                                            |
| Metrics       | Metrics Server, for `kubectl top` and autoscaling                                                            |

Set `runtime-api.env.STORAGE_CLASS` to your `gp3` class.

## Node Pools

We recommend using two separate node pools: a **general** pool for the OpenHands application services
and cluster add-ons, and a **Sysbox** pool for the agent sandboxes. Keeping sandboxes on their own
pool isolates the untrusted sandbox workload from your services, and lets the sandbox pool scale
independently, since sandboxes are created and torn down far more frequently than the services.

* **General pool**: Use standard EKS nodes on the Amazon Linux 2023 AMI, with on-demand or Spot
  capacity.
* **Sysbox pool**: Sandboxes need the Sysbox runtime, which requires an Ubuntu AMI, at least 4 vCPU
  per node, and on-demand capacity. See [Installing Sysbox](/enterprise/k8s-install/sysbox).

We recommend [Karpenter](https://karpenter.sh/) for autoscaling both pools (managed node groups also
work). Size the Sysbox pool by peak concurrent sessions, and configure it so a node is only removed
when empty, never while a session is running.

Sandboxes are pinned to the Sysbox pool automatically by the `sysbox-runc` RuntimeClass. Keep the
OpenHands services and add-ons on the general pool with a node selector.

### Sizing the Sandbox Nodes

Per-sandbox CPU, memory, and ephemeral storage are set on the
[Resource Limits](/enterprise/k8s-install/resource-limits) page. Size your Sysbox nodes around the
values you choose there. With the defaults (**0.5 vCPU**, **3 GiB memory**, **10 GiB** ephemeral),
memory is usually the binding constraint, so `m`-family instances (4 GiB per vCPU) pack most
efficiently:

| Instance      | vCPU / memory | Sandboxes per node | Bound by |
| ------------- | ------------- | ------------------ | -------- |
| `c6i.2xlarge` | 8 / 16 GiB    | \~4                | memory   |
| `m6i.2xlarge` | 8 / 32 GiB    | \~9                | memory   |
| `r6i.2xlarge` | 8 / 64 GiB    | \~14               | CPU      |
| `m6i.4xlarge` | 16 / 64 GiB   | \~19               | memory   |

Recompute these counts whenever you change the sandbox size. Also size for two more things:

* **Root volume**: ephemeral scratch is the per-sandbox ephemeral request × sandboxes per node. At
  the default 10 GiB, a full `m6i.4xlarge` needs \~190 GiB, so give Sysbox nodes a large root volume
  (200 GiB or more), or prefer more, smaller nodes.
* **Warm capacity**: a new sandbox otherwise waits for a node to boot, which takes a few minutes.
  Keeping a small pool of spare capacity (for example a low-priority placeholder Deployment sized to
  one sandbox) lets sessions start instantly. Size it to your expected burst.

## Object Storage

OpenHands stores conversation and session state in a file store. For production, we recommend using S3:

1. Create a bucket in the cluster's region.
2. Grant access with either an IAM user access key scoped to the bucket, or IRSA / EKS Pod Identity to
   avoid a long-lived credential.
3. For the access-key approach, store the credentials in a secret:

```bash theme={null}
kubectl -n openhands create secret generic openhands-s3-credentials \
  --from-literal=AWS_ACCESS_KEY_ID=<access-key-id> \
  --from-literal=AWS_SECRET_ACCESS_KEY=<secret-access-key>
```

Then point the file store at the bucket in your values:

```yaml theme={null}
filestore:
  ephemeral: false
  type: s3
  bucket: <your-bucket>
  region: <your-region>
  existingSecret: openhands-s3-credentials
```

## Database

Use an external **Amazon RDS for PostgreSQL** instance rather than the bundled database. Place it in
the cluster's VPC, reachable from the nodes on port 5432. See
[External PostgreSQL](/enterprise/external-postgres) for the values.

## Ingress

Install an ingress controller on the general pool and expose it with an **AWS Network Load
Balancer**, provisioned directly from Service annotations (no AWS Load Balancer Controller required).
Both Traefik and NGINX are supported:

* **Traefik (recommended)**: set `ingress.class: traefik` in your OpenHands values. Its default
  `TLSStore` lets one wildcard certificate serve every host.
* **NGINX**: set `ingress.class: nginx` and use `nginx.ingress.kubernetes.io/*` annotations for
  per-ingress tuning.

Expose the controller's Service as an NLB in the controller's own chart values:

```yaml theme={null}
service:
  type: LoadBalancer
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
```

Then set up certificates and DNS records for the OpenHands hostnames, see
[DNS and TLS](/enterprise/k8s-install/dns-and-tls).

## Next Steps

<CardGroup cols={2}>
  <Card title="Installing Sysbox" icon="cube" href="/enterprise/k8s-install/sysbox">
    Install the sandbox runtime on your Sysbox pool.
  </Card>

  <Card title="DNS and TLS" icon="lock" href="/enterprise/k8s-install/dns-and-tls">
    Automate records and certificates with external-dns and cert-manager.
  </Card>

  <Card title="Install with Helm" icon="ship" href="/enterprise/k8s-install/installation">
    Deploy OpenHands once the cluster is ready.
  </Card>

  <Card title="Resource Limits" icon="gauge-high" href="/enterprise/k8s-install/resource-limits">
    Size memory, CPU, and replicas for production.
  </Card>
</CardGroup>
