# Relay WS-API ingress (microk8s → LAN VM)

Terminates Let's Encrypt TLS for the relay's WebSocket API on the existing
microk8s cluster and routes the (decrypted) traffic to the relay running on a LAN
VM. The relay itself is **not** in the cluster — see `../README.md` for the VM side.

```
wss://<domain>/ws → ingress-nginx (TLS via cert-manager) → Service(no selector)
                  → Endpoints → <vm-ip>:8765 (plain ws, over the LAN)
```

A kustomize base + overlay:

```
k8s/
  base/      namespace, service+endpoints, ingress (defaults)
  overlay/   kustomization.yaml — the only file you edit
```

## Prerequisites

- microk8s with the **nginx** ingress controller and a **cert-manager
  ClusterIssuer** that already issues LE certs for your `.4qube.ru` subdomains.
- The relay running on the VM (`../install.sh`), reachable at `<vm-ip>:8765` from
  the cluster nodes (same LAN).
- DNS: `<domain>` resolves to your public IP; the router forwards 80/443 to the
  ingress (the existing cluster setup already does this).

## Configure & apply

Edit the values in [`overlay/kustomization.yaml`](overlay/kustomization.yaml) —
namespace, ingress host, TLS secret name, ingress class, cert-manager issuer, and
the relay VM IP. Preview the rendered manifests, then apply:

```bash
microk8s kubectl kustomize overlay      # dry render — eyeball the output
microk8s kubectl apply -k overlay
```

Idempotent — re-run after editing values. (Plain `kubectl`/`kustomize` work too;
`kubectl apply -k` has kustomize built in.)

## Verify

```bash
microk8s kubectl -n meshchat-relay get certificate,ingress,endpoints
```

Wait for the `certificate` to report `READY=True` (cert-manager solves the ACME
challenge through the same ingress). The `endpoints` object must list your
`<vm-ip>:8765`. Then:

```bash
# from anywhere that resolves the domain:
curl -i https://<domain>/ws        # expect HTTP 400 "Bad Request" — the WS
                                   # handler rejects a plain GET, which proves
                                   # TLS + routing to the relay work.
```

Point clients at `wss://<domain>/ws`.

## Teardown

```bash
microk8s kubectl delete -k overlay     # removes the namespace and everything in
                                       # it (service, endpoints, ingress, LE
                                       # secret). The VM is untouched.
```

## Notes

- **External-backend pattern:** a `Service` with no selector + a hand-written
  `Endpoints` of the same name is how k8s targets an off-cluster IP. Don't add a
  selector — there are no pods to match.
- Only the WS API goes through here. libp2p (8766/tcp) and TURN (8767/udp +
  media range) are forwarded straight to the VM on the router; they have their
  own transport security and can't ride an HTTP ingress.
- Values are set with JSON6902 patches (exact field paths) so changing a value
  that's also a list merge key (the ingress host) is unambiguous.
