§08 · Deploy & operate

TLS, ingress & networking

The backend serves plain HTTP and assumes you terminate TLS at the edge. What to expose, the WebSocket paths that must survive your proxy, and which way traffic flows between clusters.

Exo's backend is a single HTTP server with the UI embedded. No separate web tier, no built-in TLS. Front it with whatever ingress your platform already trusts. The one non-obvious requirement: two paths carry long-lived WebSockets, so your proxy must allow upgrades.

Ports

ports· text
1Platform (exo-app)
2 9092/tcp HTTP — UI, dashboard API, Exo Operator WebSocket, shell channel
3
4autonomic-manager (autonomic-system)
5 443 → 9443 webhook (admission reviews; TLS, cert self-bootstrapped)
6 8080 metrics (Prometheus /metrics)
7 8081 probes (/healthz, /readyz)
8 8082 invoke (agent invocation API; in-cluster or via apiserver proxy)

The platform Service is a ClusterIP on 9092; the manager Service exposes the four ports above inside autonomic-system.

TLS & ingress

Terminate TLS at your ingress controller and forward to the exo-app ClusterIP on 9092. The backend reads EXO_BASE_URL for the public origin in email links and OAuth callbacks, so set it to your HTTPS hostname.

ingress.example.yaml· yaml
1apiVersion: networking.k8s.io/v1
2kind: Ingress
3metadata:
4 name: exo
5 namespace: exo
6 annotations:
7 cert-manager.io/cluster-issuer: letsencrypt
8 nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
9spec:
10 ingressClassName: nginx
11 tls:
12 - hosts:
13 - exo.example.com
14 secretName: exo-tls
15 rules:
16 - host: exo.example.com
17 http:
18 paths:
19 - path: /
20 pathType: Prefix
21 backend:
22 service:
23 name: exo-app
24 port:
25 number: 9092

WebSockets

Exo Operator egress

In managed mode the operator opens one outbound WebSocket from its cluster to the platform at wss://<EXO_BASE_URL>/api/autonomic/connect, authenticated with the deployment token. No inbound ports open on the operator's cluster; it only needs egress to your platform host on 443. That's what keeps air-gapped and tightly-firewalled clusters working. See Connecting to the control plane.

CORS

The API responds with permissive CORS (Allow-Origin: *; methods GET/POST/PUT/PATCH/DELETE/OPTIONS; headers including Authorization and X-Tenant-ID). If you put the API behind a gateway that injects its own CORS, make sure you don't double up the headers.