Caddy
Put DNA in front of every request Caddy serves, with one imported file and no plugin.
Import one file and Caddy asks DNA about every request before your site sees it. Caddy then does what your rules ask for, Charge and Require a human included. Stock Caddy 2.8 or later, no plugin, no custom build.
Install
-
Download dna.caddy and put it beside your Caddyfile.
-
Import it once, below your global options block if you have one, and add
invoke dnato each site:import dna.caddy example.com { invoke dna reverse_proxy localhost:3000 }Put
invoke dnadirectly in the site block, anywhere in it, with no matcher. DNA then checks every request against the URL the visitor asked for, whatever yourrewriteortry_filesturn it into. With a matcher, the requests it skips reach your site unchecked, priced pages included. -
Set your API key in Caddy's environment as
DNA_API_KEY. -
Restart Caddy so it reads the new variable, for example
sudo systemctl restart caddy. A reload doesn't give a running Caddy a new environment variable.
dna.caddy uses ports 8113 and 8114 on 127.0.0.1. If something else
already does, replace every 8113 and 8114 in the file. To upgrade, replace
dna.caddy and reload Caddy; your Caddyfile stays as it is.
Installed the earlier forward_auth block? It serves Charge and Require a
human pages as ordinary pages. Remove it and its proxy on port 8113, then
install dna.caddy. Rename D3_EDGE_ADAPTER_KEY in Caddy's environment to
DNA_API_KEY and restart Caddy: under the old name the key never reaches DNA,
and nothing is enforced.
An MCP server rule that charges asks for payment on every request here, connecting and listing tools included. To charge per tool call, serve the MCP route through Vercel.
Leave headers out of your rules
DNA reads every header and cookie for your rules. Authorization and
Proxy-Authorization never reach DNA. To have DNA ignore others, list them by
name, comma-separated, in Caddy's environment, then restart Caddy:
| Variable | Ignores |
|---|---|
DNA_EXCLUDE_HEADERS | Headers, by name |
DNA_EXCLUDE_COOKIES | Cookies, by name |
Caddy still sends a listed value, and DNA drops it on arrival. To keep a header
on your server, add header_up -Name to the reverse_proxy {vars.d3_gateway}
block in dna.caddy, and again each time you replace the file.