Skip to content

Sandboxes on Kubernetes

DELEGATE runs each workspace as a pod in its own namespace. The egress proxy is the only way out of a sandbox.

infra repo clusters/fleet-dev/tenants/act creates, with sandboxes_enabled = true:

  • the namespace <installation>-sandboxes,
  • a Role there for the api-gateway (pods, services, secrets, config maps, volumes),
  • NetworkPolicies: sandbox pods reach only the egress proxy and DNS, and only the api-gateway reaches them.

The NetworkPolicies need a CNI that enforces them. Check with infrastructure/scripts/verify-sandbox-egress.sh after the apply.

With snapshots_s3_enabled = true it also creates an S3 bucket for workspace snapshots (Hetzner Object Storage) and the Secret <installation>-snapshots-s3.

VariableMeaningDefault
SANDBOX_IMAGEImage of sandbox, login and executor pods—
SANDBOX_NAMESPACENamespace of the sandboxesact-sandboxes
EGRESS_PROXY_HOSTHost and port of the egress proxy Serviceact-egress-proxy.act.svc.cluster.local:8888
API_PUBLIC_URLDELEGATE’s public API, reachable from sandboxes—
ACT_MCP_URLDELEGATE’s own MCP server, offered to every workspace—
WORKSPACE_IDLE_MINUTESStop idle workspaces after this many minutes (0 off)30
EGRESS_RETENTION_DAYSKeep egress events this long (0 keeps them)180

Sandbox pods run as a fixed non-root user (uid 1000) without capabilities or a ServiceAccount token. OpenShift’s default restricted-v2 SCC assigns a random uid instead; grant nonroot-v2 to the default ServiceAccount of the sandbox namespace so the pods keep uid 1000. OpenShift’s network plugin enforces the NetworkPolicies above.