# llmgw behind Caddy: the client-facing port (8080) on a public name, with a # certificate Caddy obtains and renews by itself. # # Replace llm.example.com, point its DNS at this machine, open 80 and 443, and # run: caddy run --config /etc/caddy/Caddyfile # # Only 8080 goes through here. 7443 (agents) is mutual TLS with the cluster's # own authority and must reach llmgw directly; 9090 and 9091 stay private. llm.example.com { # The router reads at most 32 MiB of body (router.max_body_bytes). Refusing # more here gives the client a 413 before the upload, not after it. request_body { max_size 32MB } # One control plane. With more than one, see the end of this file. reverse_proxy 127.0.0.1:8080 { # Tokens are written the moment they are generated. Without this a # streamed reply can arrive in bursts, and a client measuring time to # first token measures the proxy instead. flush_interval -1 # Caddy sets X-Forwarded-Proto and X-Forwarded-Host itself and, with # no trusted_proxies, discards whatever the client sent. llmgw relies # on that: the proto decides whether session cookies are Secure, and # the host is the base URL the landing page tells people to use. # Behind a load balancer of your own, name it in trusted_proxies. transport http { # A long generation can be silent for a while before the first # token. llmgw has its own limits (timeouts.*); this must not be # the shorter one. response_header_timeout 15m } } # No `encode` on purpose: compressing a stream buffers it. # Access log to stderr, which under systemd is the journal. log } # More than one control plane (server init --standbys, server add): one of # them leads, the others stand by. Name them all and send to the one that # leads — /leader is 200 there and 503 on a standby. Not /ready: that is 503 # on a leader with no model running yet, and would take the portal away with # it. A standby would pass a request on to the leader anyway, but not while # there is none, and the hop is for nothing. # # With a floating address (--vip) the address already follows the leader: # give reverse_proxy that one address instead, and keep the rest as above. # # llm.example.com { # request_body { # max_size 32MB # } # reverse_proxy 10.0.0.157:8080 10.0.0.158:8080 10.0.0.159:8080 { # # The first that is healthy: the leader, whichever it is. # lb_policy first # health_uri /leader # health_interval 2s # health_timeout 2s # # While leadership moves — a few seconds when a leader is lost — # # none is healthy; a request waits that long for one rather than # # failing at once. # lb_try_duration 15s # lb_try_interval 250ms # flush_interval -1 # transport http { # response_header_timeout 15m # } # } # log # }