Skip to content

OpenClaw

Deploy OpenClaw as a persistent, authenticated agent gateway using its official container image. One installation owns its device pairing, agent sessions, tools, memory and workspaces.

Features

  • Official immutable release image; singleton StatefulSet and retained state/token identity.
  • Restricted non-root runtime with the upstream tini entrypoint and no Kubernetes API token.
  • Control UI with device pairing, exact origins, private Ingress and Gateway API.
  • Explicit managed/seed configuration, named agents, provider Secrets and channel allowlists.
  • Native OTLP metrics, official collector, private Prometheus Service, ServiceMonitor and alert rules.
  • Native SQLite-consistent archives, verified S3 publication and empty-volume disaster recovery.
  • Full values schema and application behavior tests with a local model provider.

Install

Kubernetes 1.30 or newer and a suitable StorageClass are required. The image publishes Linux AMD64 and ARM64 manifests; runtime acceptance is performed on AMD64. The gateway currently supports IPv4 listeners.

Create a namespace and a provider Secret from a local environment file excluded from version control. For the default Anthropic model, include ANTHROPIC_API_KEY. Ready gateway health alone does not validate provider credentials or quota.

kubectl create namespace agents
kubectl -n agents create secret generic openclaw-provider --from-env-file=provider.env
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm upgrade --install openclaw helmforge/openclaw --namespace agents \
  --set credentials.existingSecret=openclaw-provider

OCI: oci://ghcr.io/helmforgedev/helm/openclaw. Use auth.existingSecret for render-only GitOps so offline renders do not generate different tokens. The default generated Secret is <fullname>-auth, key gateway-token; Helm upgrades preserve it by lookup.

Access and trust

Port-forward the Service to 18789 and open http://localhost:18789. Use the gateway token in the UI connection settings. Remote access needs HTTPS and an explicit allowed origin. Approve only the intended pending device; pairing is preserved across restarts. Gateway tokens authorize operator APIs and enabled tools. Keep model APIs private to trusted callers.

One release is one operator trust boundary. There is no shared-writer HA or HPA. Enable shell/browser tools only with an understood execution boundary. Upgrades require downtime; preserve a verified recovery point before schema migrations.

Guides

Examples

See simple, staging, production, custom provider and recovery. Replace hostnames, Secret names and selectors with your environment’s actual resources.

Values reference

Parameter Default Description
nameOverride "" name override setting for the gateway.
fullnameOverride "" fullname override setting for the gateway.
image.repository "ghcr.io/openclaw/openclaw" repository setting for image.
image.tag "2026.9.4@sha256:cc596b846506a5f4cfcee111394a2725f375f01cca2ebb492a161fd1b747f101" tag setting for image.
image.pullPolicy "IfNotPresent" pull policy setting for image.
imagePullSecrets [] image pull secrets setting for the gateway.
auth.existingSecret "" Existing Secret with the gateway token; empty generates and retains a token across upgrades.
auth.key "gateway-token" Secret key containing the gateway token.
credentials.existingSecret "" Existing Secret containing provider keys and TELEGRAM_BOT_TOKEN or DISCORD_BOT_TOKEN as applicable.
agent.defaults {} Additional upstream agent defaults, for example memorySearch or sandbox. Model, workspace and concurrency use the explicit fields below.
agent.entries {} Additional named agents; keep their workspace and agentDir below /home/node for chart-managed backup recovery.
agent.model "anthropic/claude-opus-4-6" Upstream provider/model identifier; inference needs the corresponding credential.
agent.toolProfile "minimal" Upstream tool profile: minimal, coding, messaging or full. Minimal permits session_status only.
agent.allowTools [] Additional upstream tool allowlist; exec and filesystem access grant access within the agent container.
agent.denyTools [] Additional upstream tool denylist.
agent.maxConcurrent 1 Maximum concurrent agent runs.
config.policy "managed" managed reconciles declared config on restart; seed preserves UI/CLI config after first initialization.
config.values {} Additional upstream configuration; chart security, state and telemetry fields are reserved.
config.agentInstructions "" Optional workspace AGENTS.md content with the selected configuration ownership policy.
config.soul "" Optional workspace SOUL.md content with the selected configuration ownership policy.
persistence.enabled true enabled setting for persistence.
persistence.existingClaim "" existing claim setting for persistence.
persistence.storageClass "" storage class setting for persistence.
persistence.accessModes ["ReadWriteOnce"] access modes setting for persistence.
persistence.size "10Gi" size setting for persistence.
persistence.retain true retain setting for persistence.
service.type "ClusterIP" type setting for service.
service.port 18789 port setting for service.
service.annotations {} annotations setting for service.
service.ipFamilyPolicy "" ip family policy setting for service.
service.ipFamilies [] ip families setting for service.
service.loadBalancerSourceRanges [] load balancer source ranges setting for service.
serviceAccount.create true create setting for serviceAccount.
serviceAccount.name "" name setting for serviceAccount.
serviceAccount.annotations {} annotations setting for serviceAccount.
resources.requests.cpu "250m" cpu setting for resources.requests.
resources.requests.memory "1Gi" memory setting for resources.requests.
resources.limits.cpu "2" cpu setting for resources.limits.
resources.limits.memory "3Gi" memory setting for resources.limits.
nodeSelector.kubernetes.io/os "linux" Upstream/Kubernetes setting.
tolerations [] tolerations setting for the gateway.
affinity {} affinity setting for the gateway.
podAnnotations {} pod annotations setting for the gateway.
extraEnv [] extra env setting for the gateway.
networkPolicy.enabled true enabled setting for networkPolicy.
networkPolicy.ingressFrom [] ingress from setting for networkPolicy.
networkPolicy.extraEgress [] extra egress setting for networkPolicy.
networkPolicy.allowInternet true allow internet setting for networkPolicy.
terminationGracePeriodSeconds 120 termination grace period seconds setting for the gateway.
ingress.enabled false enabled setting for ingress.
ingress.ingressClassName "" ingress class name setting for ingress.
ingress.annotations {} annotations setting for ingress.
ingress.hosts [{"host":"openclaw.example.com","paths":[{"path":"/","pathType":"Prefix"}]}] hosts setting for ingress.
ingress.tls [] tls setting for ingress.
gatewayAPI.enabled false enabled setting for gatewayAPI.
gatewayAPI.httpRoutes [] http routes setting for gatewayAPI.
externalSecrets.enabled false enabled setting for externalSecrets.
externalSecrets.refreshInterval "1h" refresh interval setting for externalSecrets.
externalSecrets.items [] items setting for externalSecrets.
metrics.enabled false Enable bundled diagnostics-otel metrics; no runtime plugin downloads.
metrics.intervalSeconds 15 interval seconds setting for metrics.
metrics.externalEndpoint "" External OTLP HTTP base endpoint when the local collector is disabled.
metrics.collector.enabled true enabled setting for metrics.collector.
metrics.collector.image.repository "ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib" repository setting for metrics.collector.image.
metrics.collector.image.tag "0.160.0@sha256:799dc6cf12c96192af37b5bdba804da8c10b3bc563b43cb90c3f3c58d9572ad6" tag setting for metrics.collector.image.
metrics.collector.image.pullPolicy "IfNotPresent" pull policy setting for metrics.collector.image.
metrics.collector.resources.requests.cpu "50m" cpu setting for metrics.collector.resources.requests.
metrics.collector.resources.requests.memory "64Mi" memory setting for metrics.collector.resources.requests.
metrics.collector.resources.limits.cpu "500m" cpu setting for metrics.collector.resources.limits.
metrics.collector.resources.limits.memory "256Mi" memory setting for metrics.collector.resources.limits.
metrics.serviceMonitor.enabled false enabled setting for metrics.serviceMonitor.
metrics.serviceMonitor.labels {} labels setting for metrics.serviceMonitor.
metrics.serviceMonitor.interval "30s" interval setting for metrics.serviceMonitor.
metrics.serviceMonitor.scrapeTimeout "10s" scrape timeout setting for metrics.serviceMonitor.
metrics.prometheusRule.enabled false enabled setting for metrics.prometheusRule.
metrics.prometheusRule.labels {} labels setting for metrics.prometheusRule.
metrics.prometheusRule.additionalRules [] additional rules setting for metrics.prometheusRule.
metrics.ingressFrom [] ingress from setting for metrics.
backup.enabled false enabled setting for backup.
backup.schedule "0 3 * * *" schedule setting for backup.
backup.timeZone "Etc/UTC" time zone setting for backup.
backup.suspend false suspend setting for backup.
backup.successfulJobsHistoryLimit 1 successful jobs history limit setting for backup.
backup.failedJobsHistoryLimit 2 failed jobs history limit setting for backup.
backup.activeDeadlineSeconds 1800 active deadline seconds setting for backup.
backup.stagingSize "10Gi" Ephemeral capacity for native tar.gz archive and temporary SQLite snapshots; size for peak usage.
backup.resources.requests.cpu "100m" cpu setting for backup.resources.requests.
backup.resources.requests.memory "256Mi" memory setting for backup.resources.requests.
backup.resources.limits.cpu "1" cpu setting for backup.resources.limits.
backup.resources.limits.memory "2Gi" memory setting for backup.resources.limits.
backup.s3.bucket "" bucket setting for backup.s3.
backup.s3.prefix "openclaw" prefix setting for backup.s3.
backup.s3.region "us-east-1" region setting for backup.s3.
backup.s3.endpoint "" endpoint setting for backup.s3.
backup.s3.allowInsecureEndpoint false allow insecure endpoint setting for backup.s3.
backup.s3.existingSecret "" existing secret setting for backup.s3.
backup.s3.sse "AES256" sse setting for backup.s3.
backup.s3.kmsKeyId "" kms key id setting for backup.s3.
backup.s3.caSecret "" ca secret setting for backup.s3.
backup.image.repository "public.ecr.aws/aws-cli/aws-cli" repository setting for backup.image.
backup.image.tag "2.36.43@sha256:d948ee299a7ffcaec0d6052a00b9f4c513c61cacfaedfe68b098c85808394441" tag setting for backup.image.
backup.image.pullPolicy "IfNotPresent" pull policy setting for backup.image.
backup.networkPolicy.extraEgress [] extra egress setting for backup.networkPolicy.
restore.enabled false enabled setting for restore.
restore.manifestKey "" manifest key setting for restore.
restore.maxArchiveBytes 10737418240 max archive bytes setting for restore.
restore.maxExpandedBytes 21474836480 Maximum expanded bytes accepted during recovery.
gateway.controlUi.enabled true Enable the bundled Control UI with device pairing enforced.
gateway.controlUi.allowedOrigins ["http://localhost:18789","http://127.0.0.1:18789"] Exact trusted browser origins; add the HTTPS public origin before exposing the UI.
gateway.trustedProxies [] Explicit trusted reverse-proxy IPs/CIDRs for client identity; never trust all networks.
gateway.chatCompletions.enabled false Expose authenticated OpenAI-compatible chat completions.
gateway.responses.enabled false Expose authenticated OpenResponses API.
channels.telegram.enabled false enabled setting for channels.telegram.
channels.telegram.allowFrom [] allow from setting for channels.telegram.
channels.discord.enabled false enabled setting for channels.discord.
channels.discord.allowFrom [] allow from setting for channels.discord.

Operations and configuration

OpenClaw is a personal/operator-trusted gateway. Deploy separate releases and claims for independent trust domains. There is one writer per release. Do not scale its StatefulSet or reuse its claim in another active gateway.

First access and device pairing

Port-forward the Service to local port 18789 and open http://localhost:18789. Retrieve the gateway token from the Secret named in Helm NOTES. Supply it in the Control UI connection settings. Treat token-bearing URLs as credentials and keep them out of logs and tickets. Remote browser access needs HTTPS, an exact gateway.controlUi.allowedOrigins entry, WebSocket-capable routing, and a NetworkPolicy peer allowlist.

With NetworkPolicy enabled, Ingress or Gateway API requires nonempty networkPolicy.ingressFrom selectors for the actual controller Pods/namespaces. Missing selectors fail rendering. Route names must be unique; rendered HTTPRoute names include a deterministic hash to keep long names distinct. Parent Helm global values are accepted when using this chart as a dependency; application settings and images still use this chart’s explicit values.

Remote device enrollment remains enabled. Inspect openclaw devices list in the running container and approve only the request ID associated with the intended browser using openclaw devices approve <requestId>. Local loopback connections can be auto-approved after authentication; this is not evidence of remote pairing. Do not enable dangerous device or origin bypass flags. Configure gateway.trustedProxies only for the actual reverse-proxy addresses.

Models, tools, agents and channels

Set agent.model to an upstream provider/model ID and supply its environment key through credentials.existingSecret. Custom provider definitions belong in config.values.models.providers; use SecretRef or environment placeholders for API keys, never literal credentials in values. An OpenAI-compatible backend normally uses api: openai-completions.

agent.toolProfile defaults to minimal. Add specific tools with agent.allowTools; deny unwanted tools with agent.denyTools. Filesystem tools are workspace-limited and elevated execution is disabled. Shell execution still has access to the container’s writable data and environment. Kubernetes hardening does not turn mutually untrusted agents into isolated tenants. Configure upstream remote sandboxing in agent.defaults.sandbox when needed and independently validate the selected remote service. The chart does not mount a Docker socket or grant cluster permissions.

agent.defaults accepts additional upstream settings, such as memory search and heartbeat. agent.entries adds named agents; state and workspace paths must remain below /home/node for automated recovery. Model routing and other non-secret upstream settings can be supplied in config.values. Keep application state on the persistent home volume.

Telegram and Discord are opt-in and require nonempty allowFrom lists plus their upstream environment token in the credentials Secret. Group traffic is disabled by the simple chart contract. Test account access and permissions before connecting real users. External APIs, channels and browser services have their own permissions and recovery requirements.

Ownership and upgrades

Managed mode applies declared JSON, AGENTS.md and SOUL.md on initialization. Existing state and sessions are preserved; operator edits to managed files are overwritten at the next restart. Empty instruction values leave those workspace files unmanaged. Seed mode initializes missing files only; subsequent UI/CLI edits are authoritative. Updating values in seed mode does not overwrite existing config. Back up before deliberately replacing or reseeding an existing file.

Rotate external credentials by updating the Secret and restarting the StatefulSet. Keep the generated gateway Secret with retained state; changing a token deliberately can require updating clients. Uninstall retains the chart-created claim and generated Secret by default. Reinstall with the same release identity to reuse them, or explicitly reference the retained resources. Claims are independent of StatefulSet recreation.

Before upgrading, create and verify a recovery point, review upstream migrations and schedule downtime. Kubernetes owns restarts and the image is immutable: do not run self-update inside the gateway. Helm rollback does not reverse database migrations. If an older release cannot read the upgraded schema, recover a pre-upgrade archive into a new claim.

Health and networking

Startup/readiness inspect /startupz JSON; liveness inspects /healthz. /readyz includes individual channel health and is useful for diagnosis without evicting the entire UI when a channel is down. Probes reject the UI’s HTML fallback. The current upstream gateway binds IPv4; IPv6 Service requests are rejected by the chart.

NetworkPolicy denies ingress unless callers are explicitly selected. Default egress permits cluster DNS and public HTTPS; private model servers, MCP, remote browsers and non-HTTPS services need networkPolicy.extraEgress. Ingress controllers also require an ingress peer rule. Controller-specific TLS redirects and WebSocket timeouts must be configured at the edge.

Native backup and S3 recovery

Enable backup.enabled with a persistent claim, an S3 bucket and an existing credential Secret. The CronJob uses concurrencyPolicy: Forbid, a deadline and no automatic Job retries. It schedules on the gateway’s node so RWO storage can be mounted concurrently; ReadWriteOncePod is incompatible with this online backup workflow.

The snapshot init container runs OpenClaw’s native backup create --verify --json. The archive includes discovered state, configured agent roots, config dependencies, credentials and workspaces. Canonical SQLite databases use online snapshots, including committed WAL data, and native integrity/ownership verification. This is per-database consistency, not one transaction spanning every database and workspace file. Third-party SQLite files outside owned agent roots may be ordinary file copies. Quiesce the application if cross-file atomicity is required.

Native backups deliberately remove transient leases and delivery queue records. Recovery is not an exactly-once continuation of external actions. Some logs, volatile files and plugin dependency trees are excluded. Protect exports or custom external data separately. Kubernetes Secrets, model-provider accounts, external browser state and object storage are not restored by an application archive.

The AWS CLI container receives only the completed archive volume and S3 credentials. It uploads to a unique run prefix, reads the remote archive back to verify SHA-256, then uploads the completion manifest last. Only a successful Job and completed manifest establish offsite success; OpenClaw’s local backup status alone does not. Interrupted runs can leave objects without a manifest. Configure bucket lifecycle for retention and incomplete multipart uploads.

Use HTTPS; a private endpoint can use a CA Secret with ca.crt. HTTP requires an explicit insecure-endpoint opt-in for trusted environments. SSE-S3 and SSE-KMS are supported; configure KMS permissions separately. Backups contain credentials and conversation state: scope the storage identity to the required prefix and protect object access. Checksums detect corruption but are not signatures against an attacker who can rewrite both archive and manifest.

Recovery procedure

  1. Select a completed manifest and preserve the old deployment/state for investigation.
  2. Use a new empty claim and the matching upstream image version. Stop any writers that might use that destination.
  3. Configure restore.enabled, restore.manifestKey, S3 credentials and size limits. Keep messaging disconnected while validating the recovered installation.
  4. Init containers download bounded data, validate checksum and native archive integrity, extract to staging, and activate assets into empty persisted home. External asset paths are rejected for automatic activation and need manual recovery.
  5. Confirm gateway health, known sessions, workspaces and credentials before reconnecting external channels. Review pending actions; ratchet-based credentials can require relinking after rollback.
  6. A completion marker makes restarting the same restored release idempotent. Changing the manifest on existing state is rejected. Interrupted activation leaves a marker and requires inspection and a fresh claim; it never overwrites state.

Staging needs room for the archive and snapshot scratch space. Restore additionally needs extracted data plus the final state copy. backup.stagingSize is an emptyDir ceiling, not reserved disk; provision node ephemeral capacity and scheduling resources accordingly. The native archive has no universal data-size limit; chart restore limits bound downloads and expanded entries. Test recovery with representative data and storage throughput before setting deadlines.

Observability

metrics.enabled activates the release-bundled diagnostics-otel plugin. The gateway exports native metrics over OTLP HTTP to a loopback collector. The pinned official collector translates metrics into Prometheus format on a separate private Service, port 8889. Enable metrics.serviceMonitor.enabled for an installed Prometheus Operator and set its discovery labels and metrics.ingressFrom peer selectors. When NetworkPolicy is enabled, an enabled ServiceMonitor without these selectors fails rendering.

This integration does not install the separate diagnostics-prometheus plugin at startup and does not share the gateway operator token with the scraper. The collector receives metrics only; prompt/tool content capture, traces and logs are disabled. Native usage and latency series depend on activity and provider reporting. They are operational observations, not guaranteed billing records. Empty activity-dependent series are expected before requests occur.

To use an existing OTLP collector, disable the local collector and set metrics.externalEndpoint to its OTLP HTTP base URL, such as https://collector.example.com, or its complete /v1/metrics URL. Allow the destination in NetworkPolicy. ServiceMonitor and chart Prometheus rules require the local collector. External collector authentication and TLS policy can be supplied through supported upstream environment configuration in the credentials Secret; verify the endpoint integration in your environment.

The optional PrometheusRule detects failed scrapes; add deployment-specific alerts with additionalRules. Also monitor gateway readiness, restart count, PVC fullness, node ephemeral storage and failed/missing scheduled backup Jobs. A local OpenClaw backup success record does not prove S3 publication. Kubernetes Job completion and the remote manifest do.