# Caddy reverse proxy for the Zopu VDS staging agent stack. # # This is the ONLY public ingress to the single agents Node process (see # docs/DEPLOYMENT_PLAN.md §"Public surface"). It terminates TLS for # agents.zopu.puter.wtf — the Flue callback hostname Convex reaches — then # forwards ONLY the documented worker paths to the internal `agents` service at # 127.0.0.1:3000. # # Hard rules this file enforces: # - No generic /api/* proxy and no browser-to-Flue traffic (DEPLOYMENT_PLAN.md # line 86). Browsers talk only to Convex. # - Only the paths the Convex backend actually calls are routed: # /health liveness probe # /internal/project-setup single-call project setup coordinator # /internal/agents//events agent event dispatch callback # - The AgentOS registry runs in-process as a native envoy (Rivet Mode A), # so there is no /internal/rivet/* route to expose. Exposing a private # worker protocol publicly would widen the attack surface needlessly. # - Former routes (/agents/zopu/*, /internal/work-attempts/*, /workflows/*, # /api/rivet/*) are intentionally absent: they are stale and not part of the # current Convex→agents contract. # - Everything else returns 404. The private worker protocol stays narrow. # # TLS certs persist in Caddy's data directory. Caddy serves its own ACME # HTTP-01 challenge responses on :80 automatically, so the :80 block only # redirects everything else to HTTPS — worker traffic is never served over # plain HTTP. # # Install/update: see the "Caddy" section of deploy/vds/README.md. In short, # copy this file to /etc/caddy/Caddyfile, then: # sudo caddy validate --config /etc/caddy/Caddyfile # sudo systemctl reload caddy agents.zopu.puter.wtf { encode zstd gzip # Explicit route block pins directive order: path-matched proxies run # first, then the terminal 404 fallback. No directive is left to the # default sort. route { # Liveness probe (CI healthcheck). Routed to the real worker so a failed # process is not masked by a synthetic success. reverse_proxy /health 127.0.0.1:3000 # Single-call project setup coordinator. Requires the internalRoute bearer. reverse_proxy /internal/project-setup 127.0.0.1:3000 # Agent event dispatch callback. Requires the internalRoute bearer. reverse_proxy /internal/agents/* 127.0.0.1:3000 # Everything else is not part of the private worker protocol. respond 404 } } # HTTP → HTTPS redirect (Caddy still answers ACME challenges on :80). :80 { redir https://{host}{uri} permanent }