{ # Automatic HTTPS. Caddy asks Let's Encrypt on its own; the host has to be reachable from the # internet on 80 or 443 for the challenge, which this VM is. # # One thing to know before choosing the name. CAA says who may issue, and isti.cnr.it # authorises digicert.com and sectigo.com for a plain name, with Let's Encrypt allowed for # wildcards only. That is not the obstacle it looks like: CAA is evaluated on the canonical # name, so a friendly name that is a CNAME into a zone which does authorise Let's Encrypt is # issued without trouble - which is exactly how the institute's own hosts already work. # A name pointing straight at an address with an A record, under isti.cnr.it, would be refused. # # If issuance is ever refused, Caddy's log says so in as many words. The way out is a # certificate obtained by hand: # # auto_https off (in this block) # tls /certs/host.pem /certs/host-key.pem (in the site block) # # and mount /certs read-only. The private key of a name the whole institute trusts does not # belong in an image, and even less in one built to run code an agent wrote. admin off email {$MCP_TLS_CONTACT} } {$MCP_SITE_ADDRESS} { handle_path /coding-agent/* { reverse_proxy coding-agent-mcp:3000 { flush_interval -1 } } handle_path /dev-server/* { reverse_proxy dev-server-mcp:3000 { flush_interval -1 } } handle_path /browser/* { reverse_proxy browser-mcp:3000 { flush_interval -1 } } # The one door a person opens, as opposed to the three above, which a machine opens with an API # key. handle_path strips the prefix, so the worker's proxy sees //... and the # application behind it sees the path it would see at the root. # # Same origin as the MCP endpoints above, which is a compromise worth naming: JavaScript in a # previewed page can reach /dev-server/mcp. It gets 401 - those endpoints authenticate by # bearer token, never by cookie, so there is no ambient authority for a page to borrow - and # the preview's own cookie is scoped to /preview// and travels nowhere else. handle_path /preview/* { reverse_proxy dev-server-worker:4500 } handle { respond "No MCP server is published at this path" 404 } # One line per request. This gateway is the only door into a machine that runs code an agent # wrote, so it should be able to say who knocked. Caddy redacts Authorization and Cookie in its # access log by default, so the token itself is not written down. log { output stdout format json } }