|
| 1 | +# Deploy OpenClaw on OpenShift in 5 Minutes |
| 2 | + |
| 3 | +OpenClaw is an open-source AI agent gateway — a platform for running, managing, and observing AI agents. |
| 4 | +This guide gets you from zero to a running OpenClaw instance on OpenShift, with OpenShift OAuth protecting the |
| 5 | +UI and enterprise security hardening out of the box. |
| 6 | + |
| 7 | +## Why OpenShift? |
| 8 | + |
| 9 | +OpenClaw runs on any Kubernetes cluster, but OpenShift adds layers of security that matter when you're |
| 10 | +running AI agents that can call tools, execute code, and interact with external services. |
| 11 | + |
| 12 | +### What OpenShift gives you for free |
| 13 | + |
| 14 | +**OAuth integration** — OpenClaw's deployment includes an [oauth-proxy](https://github.com/openshift/oauth-proxy) |
| 15 | +sidecar that authenticates users against OpenShift's built-in OAuth server. No external identity provider to configure. |
| 16 | +If you can `oc login`, you can access your agent. |
| 17 | + |
| 18 | +**Security Context Constraints (SCCs)** — OpenShift's default `restricted-v2` SCC enforces a strict posture on every container: |
| 19 | + |
| 20 | +- Runs as a random, non-root UID assigned by the namespace |
| 21 | +- Read-only root filesystem |
| 22 | +- All Linux capabilities dropped |
| 23 | +- No privilege escalation |
| 24 | + |
| 25 | +The OpenClaw gateway runs happily under `restricted-v2` with no custom SCC required. Every container in the pod — gateway, |
| 26 | +oauth-proxy, and init-config — runs unprivileged with `allowPrivilegeEscalation: false` |
| 27 | +and `capabilities.drop: [ALL]`. |
| 28 | + |
| 29 | +**Routes with TLS** — OpenShift Routes provide automatic TLS termination via the cluster's wildcard certificate. The gateway listens on loopback only (`127.0.0.1:18789`) — all external traffic goes through the oauth-proxy, which handles authentication before forwarding to the gateway. |
| 30 | + |
| 31 | +### The pod architecture |
| 32 | + |
| 33 | +``` |
| 34 | + ┌─── OpenShift Route (TLS) ───┐ |
| 35 | + │ │ |
| 36 | + ▼ │ |
| 37 | + ┌─────────────┐ │ |
| 38 | + │ oauth-proxy │ ◄── OpenShift OAuth │ |
| 39 | + │ (port 8443)│ │ |
| 40 | + └──────┬──────┘ │ |
| 41 | + │ authenticated │ |
| 42 | + ▼ │ |
| 43 | + ┌─────────────┐ │ |
| 44 | + │ gateway │ ◄── loopback only │ |
| 45 | + │ (port 18789)│ read-only root │ |
| 46 | + └─────────────┘ all caps dropped │ |
| 47 | + ┌─────────────┐ │ |
| 48 | + │ init-config │ ◄── runs at start │ |
| 49 | + │ (init cont) │ copies config→PVC │ |
| 50 | + └─────────────┘ │ |
| 51 | + │ |
| 52 | + PVC (/home/node/.openclaw) ◄───────────────────┘ |
| 53 | + Config, sessions, agent workspaces |
| 54 | +``` |
| 55 | + |
| 56 | +All containers run under `restricted-v2`. No custom SCC. No cluster-admin for the workload itself. |
| 57 | + |
| 58 | +### What the platform deploys |
| 59 | + |
| 60 | +Beyond the pod, the setup script creates namespace-level security resources: |
| 61 | + |
| 62 | +| Resource | Purpose | |
| 63 | +|----------|---------| |
| 64 | +| **ResourceQuota** | Caps the namespace at 4 CPU / 8Gi RAM requests, 20 pods, 100Gi storage | |
| 65 | +| **PodDisruptionBudget** | `maxUnavailable: 0` — protects the pod during node maintenance | |
| 66 | +| **ServiceAccount** | Dedicated SA for the oauth-proxy (no API permissions granted) | |
| 67 | +| **OAuthClient** | Cluster-scoped — registers the instance with OpenShift's OAuth server | |
| 68 | + |
| 69 | +The gateway container has zero Kubernetes API permissions. It talks to model |
| 70 | +providers (Anthropic, OpenAI, Vertex AI, etc.) over HTTPS and serves the UI on loopback. That's it. |
| 71 | + |
| 72 | +## Prerequisites |
| 73 | + |
| 74 | +- An OpenShift cluster (4.x) where you can create a namespace |
| 75 | +- `oc` CLI authenticated (`oc login`) |
| 76 | +- An API key for at least one model provider (Anthropic, OpenAI, Google, etc.) |
| 77 | + |
| 78 | +The OAuthClient is a cluster-scoped resource. If you don't have cluster-admin, the script will print the |
| 79 | +exact command to give your admin — it's a single `oc apply`. |
| 80 | + |
| 81 | +## Deploy |
| 82 | + |
| 83 | +```bash |
| 84 | +git clone https://github.com/redhat-et/openclaw-k8s.git |
| 85 | +cd openclaw-k8s |
| 86 | +./scripts/setup.sh |
| 87 | +``` |
| 88 | + |
| 89 | +The script is interactive. It will prompt you for: |
| 90 | + |
| 91 | +1. **Namespace prefix** — your name or team (e.g., `alice`). Creates the namespace `alice-openclaw`. |
| 92 | +2. **Agent name** — a display name for your default agent (e.g., `Atlas`, `Scout`, `Raven`). |
| 93 | +3. **API key** — for your model provider. The script detects `ANTHROPIC_API_KEY` from your environment automatically, or |
| 94 | +prompts for it. |
| 95 | + |
| 96 | +Everything else is auto-generated (gateway token, OAuth secrets, cookie secrets) and saved to `.env` (git-ignored). |
| 97 | + |
| 98 | +The script builds a `generated/` directory with processed templates, deploys via kustomize, waits for the pod to be |
| 99 | +ready, and installs agent workspace files. Total time: about 2 minutes, most of it waiting for the image pull. |
| 100 | + |
| 101 | +## Access your instance |
| 102 | + |
| 103 | +The Route URL is printed at the end of setup: |
| 104 | + |
| 105 | +``` |
| 106 | +Access URLs: |
| 107 | + OpenClaw Gateway: https://openclaw-alice-openclaw.apps.your-cluster.example.com |
| 108 | +``` |
| 109 | + |
| 110 | +OpenShift OAuth handles authentication — you'll be redirected to the OpenShift login page. After authenticating, the |
| 111 | +Control UI asks for your **Gateway Token**: |
| 112 | + |
| 113 | +```bash |
| 114 | +grep OPENCLAW_GATEWAY_TOKEN .env |
| 115 | +``` |
| 116 | + |
| 117 | +Paste it in, and you're in. |
| 118 | + |
| 119 | +## What you get |
| 120 | + |
| 121 | +A running OpenClaw gateway with: |
| 122 | + |
| 123 | +- **Your named agent** — an interactive AI agent backed by the model provider you configured |
| 124 | +- **WebChat UI** — browser-based chat interface |
| 125 | +- **Control UI** — agent management, session history, configuration |
| 126 | +### Talk to your agent |
| 127 | + |
| 128 | +Open the WebChat UI from the Control UI sidebar, select your agent, and start chatting. The agent has access to the |
| 129 | +tools configured in your gateway — by default, a general-purpose assistant backed by your chosen model. |
| 130 | + |
| 131 | +### Add more agents |
| 132 | + |
| 133 | +Deploy additional pre-built agents (resource optimizer, MLOps monitor) with scheduled jobs: |
| 134 | + |
| 135 | +```bash |
| 136 | +./scripts/setup-agents.sh |
| 137 | +``` |
| 138 | + |
| 139 | +Or scaffold your own: |
| 140 | + |
| 141 | +```bash |
| 142 | +./scripts/add-agent.sh |
| 143 | +``` |
| 144 | + |
| 145 | +## Model options |
| 146 | + |
| 147 | +The setup script supports multiple model providers. You can also change models after deployment by editing the config. |
| 148 | + |
| 149 | +| Provider | Model | How to configure | |
| 150 | +|----------|-------|-----------------| |
| 151 | +| Anthropic | `anthropic/claude-sonnet-4-6` | `ANTHROPIC_API_KEY` env var or interactive prompt | |
| 152 | +| OpenAI | `openai/gpt-4o` | Interactive prompt during setup | |
| 153 | +| Google Vertex AI | `google-vertex/gemini-2.5-pro` | `--vertex` flag, requires GCP project | |
| 154 | +| Claude via Vertex | `anthropic-vertex/claude-sonnet-4-6` | `--vertex --vertex-provider anthropic` | |
| 155 | +| In-cluster vLLM | Any model on your GPU node | Set `MODEL_ENDPOINT` to your vLLM `/v1` URL | |
| 156 | + |
| 157 | +## Teardown |
| 158 | + |
| 159 | +```bash |
| 160 | +./scripts/teardown.sh |
| 161 | +``` |
| 162 | + |
| 163 | +Removes the namespace, all resources, the OAuthClient, and the `generated/` directory. Your `.env` is kept |
| 164 | +unless you pass `--delete-env`. |
| 165 | + |
| 166 | +## Next steps |
| 167 | + |
| 168 | +| What | How | |
| 169 | +|------|-----| |
| 170 | +| Deploy more agents | `./scripts/setup-agents.sh` | |
| 171 | +| Create a custom agent | `./scripts/add-agent.sh` | |
| 172 | +| Add scheduled jobs | Create a `JOB.md` in your agent directory, run `./scripts/update-jobs.sh` | |
| 173 | +| Enable observability | `./scripts/deploy-otelcollector.sh` (requires OTEL Operator + MLflow) | |
| 174 | +| Enable zero-trust A2A | Redeploy with `./scripts/setup.sh --with-a2a` (requires [Kagenti](https://github.com/kagenti/kagenti)) | |
| 175 | +| Full architecture docs | [A2A-ARCHITECTURE.md](https://github.com/redhat-et/openclaw-k8s/blob/main/docs/A2A-ARCHITECTURE.md), [TEAMMATE-QUICKSTART.md](https://github.com/redhat-et/openclaw-k8s/blob/main/docs/TEAMMATE-QUICKSTART.md) | |
| 176 | + |
| 177 | +## Links |
| 178 | + |
| 179 | +- **Repository**: [github.com/redhat-et/openclaw-k8s](https://github.com/redhat-et/openclaw-k8s) |
| 180 | +- **OpenClaw**: [github.com/openclaw](https://github.com/openclaw) |
| 181 | +- **Kagenti** (zero-trust A2A): [github.com/kagenti/kagenti](https://github.com/kagenti/kagenti) |
0 commit comments