4 · mTLS

Generate a full CA + server + client chain, then require client certs.

What it is

tls.cert/tls.key turn on HTTPS; adding tls.client_ca makes it mutual TLS — the server requires and verifies a client certificate signed by that CA before it will even read the request body.

Why

Stronger than bearer tokens for machine-to-machine traffic (service-to-service inside a VPC, a fleet of workers, CI runners): possession of a private key, not a copied header value, is what proves identity, and a bad client is rejected at the TLS handshake — before any application code, routing, or upstream call runs.

Configure

generate + configure
routsi certs   # → ~/.config/routsi/certs/{ca,server,client}.{crt,key}
models.yaml
tls:
  cert: ~/.config/routsi/certs/server.crt
  key: ~/.config/routsi/certs/server.key
  client_ca: ~/.config/routsi/certs/ca.crt
call it
curl -i https://localhost:8080/v1/chat/completions \
  --cacert ~/.config/routsi/certs/ca.crt \
  --cert ~/.config/routsi/certs/client.crt \
  --key ~/.config/routsi/certs/client.key \
  -d '{"model":"auto","messages":[{"role":"user","content":"hi"}]}'
# → 200. Omit --cert/--key → TLS handshake fails before the request is even read.

How to adapt

Drop tls.client_ca to keep plain server-side HTTPS without requiring client certs. To issue certs for additional clients, reuse the CA generated by routsi certs (ca.crt/ca.key) with your own tooling (or re-run routsi certs for another client/server pair) rather than generating a second, unrelated CA — the server only trusts client certs signed by the CA named in client_ca. Combine with token auth if you want both a network-level and application-level check.

Next: Agent session that remembers →