UI Access
Clu's frontend is served from a ClusterIP Service on port 8080. Three
paths cover every deployment:
- Port-forward — local dev, first-install smoke testing.
- Ingress — standard production path with your existing ingress controller (ALB / nginx / Traefik).
- Ingress + Cognito auth — production with SSO enforcement.
Port-forward (default)
kubectl port-forward -n clu-ops svc/clu-ops-agent 8080:8080
Open http://localhost:8080. Works on every K8s distribution, no
additional dependencies. Forward breaks on pod restart — the
./scripts/clu-open.sh helper wraps kubectl port-forward in a
reconnecting loop for demos + dev.
Use for first-install smoke, individual-operator debugging, or any environment where exposing Clu via ingress is overkill.
Ingress (production)
Clu works with any ingress controller that supports standard
networking.k8s.io/v1 Ingress. Example with ingress-nginx:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: clu-ops-agent
namespace: clu-ops
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "1m"
# SSE endpoints need long timeouts for streaming chat.
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
spec:
ingressClassName: nginx
rules:
- host: clu.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: clu-ops-agent
port:
number: 8080
tls:
- hosts: [clu.example.com]
secretName: clu-example-tls
For AWS ALB via the AWS Load Balancer Controller:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: clu-ops-agent
namespace: clu-ops
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internal # or internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-redirect: "443"
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:...
spec:
rules:
- host: clu.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: clu-ops-agent
port:
number: 8080
Important — SSE streaming: the /api/query endpoint streams chat
responses via Server-Sent Events. Long-lived connections can hit default
idle timeouts. Set:
- nginx:
proxy-read-timeout: 3600+proxy-send-timeout: 3600 - ALB:
alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=3600 - Cloudflare / other CDNs: disable caching on
/api/*, set origin timeout ≥ 3600s.
Chats feel fine at 60s timeout for short answers; complex diagnostic flows with many tool calls can exceed that.
Ingress + Cognito auth (recommended for production)
Putting Clu behind auth is the standard deployment — production installs shouldn't be reachable without SSO. ALB + Cognito example:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: clu-ops-agent
namespace: clu-ops
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:...
alb.ingress.kubernetes.io/auth-type: cognito
alb.ingress.kubernetes.io/auth-scope: openid
alb.ingress.kubernetes.io/auth-session-timeout: "28800"
alb.ingress.kubernetes.io/auth-idp-cognito: |
{
"UserPoolArn": "arn:aws:cognito-idp:us-east-1:...:userpool/...",
"UserPoolClientId": "...",
"UserPoolDomain": "clu-auth"
}
alb.ingress.kubernetes.io/auth-on-unauthenticated-request: authenticate
spec:
rules:
- host: clu.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: clu-ops-agent
port:
number: 8080
For nginx + oauth2-proxy, the standard oauth2-proxy sidecar pattern
works — Clu doesn't need auth-aware chart templating.
Multi-cluster considerations
Clu is namespace-scoped to clu-ops in each cluster where it
runs. Multi-cluster environments install one Clu pod per cluster; there's
no cross-cluster federation in v0.0.1. Operators who want one pane of
glass across N clusters use N separate ingress hostnames
(clu-prod.example.com, clu-staging.example.com) — each Clu instance
has full visibility into its own cluster + whatever AWS resources its
IRSA role grants access to.
Local-development ingress
For local kind development, the bundled setup script configures
extraPortMappings so port 8080 / 8443 on the host reach the
ingress-nginx controller inside kind. Combined with the test-cluster
setup, the Clu UI is reachable at http://clu.localtest.me:8080
without a port-forward (localtest.me always resolves to
127.0.0.1).
What the frontend needs from the backend
The React SPA makes all API calls relative — there's no hardcoded
backend URL. The nginx.conf inside the frontend container reverse-proxies
/api to http://localhost:8081 (the backend container in the same
pod). Any ingress that terminates at the Service port forwards both
/ (SPA) and /api/* (backend) through the same path.
No CORS config needed.