# Gateway API Instance Access Configuration The ClawOS instance UIs (OpenClaw web / noVNC / filebrowser) and the MS Teams callback can be exposed through a single Gateway API entry point. All an administrator has to do is prepare one labeled Gateway in the cluster; ClawOS picks it up automatically when an instance is created and generates the HTTPRoute. If no usable Gateway is found, the instance falls back to direct NodePort access — creation is never blocked. The minimum configuration is two steps: label the Gateway with `agentclaw.io/gateway: "true"`, then use the `agentclaw.io/base-url` annotation to tell ClawOS the address users access from outside. Details follow. ## Prerequisites - The Gateway API CRDs (`gateway.networking.k8s.io/v1`) and a matching GatewayClass controller (kgateway, Envoy Gateway, Istio, and so on) are installed in the cluster. - The controller must pass WebSocket traffic through: both OpenClaw and noVNC use WS. The instance Services generated by ClawOS already carry `appProtocol: kubernetes.io/ws` on the relevant ports, which some implementations (kgateway) rely on to allow WebSocket. ## Requirements the Gateway Must Meet Every condition below is mandatory. A Gateway that fails any of them is skipped silently (no error is raised; the instance simply falls back to NodePort): | Condition | Description | | --- | --- | | Label `agentclaw.io/gateway: "true"` | The value must be the string `"true"` | | At least one listener with `protocol` set to `HTTP` or `HTTPS` | TCP / TLS / UDP listeners cannot carry an HTTPRoute | | That listener has `allowedRoutes.namespaces.from` set to `All` | Must be written explicitly | | That listener leaves `allowedRoutes.kinds` unset, or includes `HTTPRoute` | A listener that declares only GRPCRoute is unusable | | An external access address can be determined | That is, either a valid `agentclaw.io/base-url` annotation is set, or `status.addresses` is non-empty. See the next section | !!! note ClawOS does not check the Gateway's `Accepted` / `Programmed` conditions. A Gateway can still be selected before its controller has finished programming it — the HTTPRoute is created successfully, but it only becomes reachable once the controller is ready. Example (HTTPS listener with an explicit external domain): ```yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: clawos-gateway namespace: public labels: agentclaw.io/gateway: "true" annotations: agentclaw.io/base-url: https://agentclaw.example.com spec: gatewayClassName: kgateway listeners: - name: https port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: agentclaw-tls allowedRoutes: namespaces: from: All ``` ## External Access Address (`agentclaw.io/base-url`) This address is concatenated directly with the `/agentclaw//...` prefix to form the access link handed to users, so it must be **the address the user's browser actually reaches**, not an in-cluster address. ### Option 1: Set the Annotation Explicitly (Recommended) Once the annotation exists it takes precedence and `status.addresses` is no longer consulted. The format must be `scheme://host[:port]`. An invalid value makes the entire Gateway unusable (fallback to NodePort). ### Option 2: Omit the Annotation and Derive Automatically The first non-empty `value` in `status.addresses` is taken and combined into `://`. The `:` suffix is appended only when the listener port is not the default port for that protocol (HTTP 80 / HTTPS 443); IPv6 addresses are bracketed automatically. ## How a Gateway Is Chosen When There Are Several - All labeled Gateways in the cluster are listed and sorted by `namespace/name`; the **first one satisfying the conditions above** is used. This ordering exists only to make the result reproducible — it does not mean the first one is "more suitable". **Keeping exactly one labeled Gateway per cluster is recommended.** - When one Gateway has multiple listeners, `HTTPS` takes priority over `HTTP`; listeners with the same protocol are ordered by listener `name`. This ordering only affects the automatically derived scheme and port; it has no effect on the final address when the annotation is set. ## Generated Routes When an instance is created, ClawOS creates an HTTPRoute named `agent-route-` **in the instance's own namespace**, with `parentRefs` pointing at the selected Gateway and ownerReferences set (so it is reclaimed automatically when the instance is deleted). Path prefixes: | Path prefix | Backend | | --- | --- | | `/agentclaw//openclaw` | OpenClaw UI | | `/agentclaw//vnc` | noVNC | | `/agentclaw//files` | filebrowser | | `/agentclaw//msteams` | MS Teams callback (port 3978) | Each prefix is rewritten to `/` via `ReplacePrefixMatch` before being forwarded to the instance Service. If there is another reverse proxy in front of the Gateway, make sure it passes these paths through verbatim and does not strip the prefix again. ## When Settings Take Effect, and Troubleshooting - The Gateway is evaluated only when an instance is **created or updated**. Adding a Gateway or changing the annotation afterwards does not rewrite the HTTPRoute or access address of existing instances; the instance must be updated for the selection to run again. - A failure at any step (no candidate Gateway, no usable listener, invalid annotation, no address available) never blocks instance creation — it only falls back to direct NodePort access. - To troubleshoot, raise the apiserver log level to `-v=2` and search for `No usable access gateway`. The `reason` field gives the specific cause for each Gateway, for example `invalid agentclaw.io/base-url annotation: gateway base URL must not contain a path`.