-
Notifications
You must be signed in to change notification settings - Fork 1
FAQ
markdown_for_agents /var/www/site # WRONG — silently broken
markdown_for_agents { root /var/www/site } # rightAny first argument starting with / is consumed by Caddy as a path
matcher (/var/www/site), not as a positional argument. The
directive would only fire for requests to literally /var/www/site,
with an empty root. The module won't error — it'll just never run.
Symptom: you curl ... -H "Accept: text/markdown" and get HTML back
with no Vary: Accept, no ETag. Fix is always to use the block form.
The static-first path serves matched files directly without calling the
next handler. That means any basicauth, forward_auth, jwtauth, or
similar middleware that comes after markdown_for_agents in the
Caddyfile chain will not run for Markdown responses.
In practice Caddy automatically orders this directive immediately before
file_server, and the default placement of auth middleware (which is
before file_server) is safe. Auth runs first; Markdown serving runs
after. ✓
You'd only have an ordering problem if:
- You explicitly put auth in a
routeblock aftermarkdown_for_agents - You use a
handleblock with non-default ordering - You apply path matchers that only target
*.html(also match the URL suffix you've configured for Markdown, e.g.path *.html *.md)
When in doubt, wrap both in one handle:
handle {
basicauth { ... }
markdown_for_agents { root /srv }
file_server
}Check that the matched route includes the directive. A common mistake:
example.com {
@html path *.html
route @html {
markdown_for_agents { root /srv }
file_server
}
}/foo.md doesn't match @html, so it falls through to nothing. Add
*.md to the matcher:
@html path *.html *.mdIt shouldn't — the module only converts responses with
Content-Type: text/html. If you're seeing this, you probably have a
backend that mislabels JSON as HTML. Check the upstream response
headers.
That's Cloudflare (or any compressing reverse-proxy) appending -gzip
to indicate the entity body was transformed by transparent compression.
The strong ETag this module emits is still the source of truth; CF
strips the suffix on the If-None-Match comparison server-side.
Two knobs:
-
pregenerate— warm the cache at startup (paid at provision time) - Persistent
cache_dir— survives restarts, so a deploy with the same content has a warm sidecar cache from the first request
Combining both is fine.
convert_timeout (default 5s) returned. You can:
- Raise
convert_timeoutif your HTML is genuinely large - Raise
max_concurrentif conversions queue - Lower
max_body_bytesto short-circuit converting giant pages
The 503 is intentional — the alternative is unbounded goroutine growth under thundering-herd conditions.
That's a feature, not a bug. The shared cache is, well, shared, so
authenticated responses are bypassed by default. If your content is
genuinely identical for all users at this URL, set
allow_authenticated. Otherwise, leave the safe default alone.
Default: <caddy-data-dir>/md4agents/<sha256-prefix-of-root>/. The
SHA-prefix segment avoids ever writing the original path basename into
the data dir (information-leak hygiene). Override with cache_dir.
Yes, with explicit routes:
example.com {
handle /docs/* {
markdown_for_agents { root /srv/docs main_selector article }
file_server { root /srv/docs }
}
handle /blog/* {
markdown_for_agents { root /srv/blog main_selector .post }
file_server { root /srv/blog }
}
}Each instance has independent caches, configs, and selectors. The cache
dirs are derived from root so they don't collide.
markdown_for_agents {
cache_size 0
cache_ttl never
}…but you really shouldn't. The cache is the entire performance story.
A cache_size 0 config converts every request from scratch.
Yes. The module is transport-agnostic — it operates on the request and response at the handler level. Caddy's QUIC/H3 listener is unaffected.
Yes — the converter is
html-to-markdown/v2
which handles tables, fenced code (<pre><code> → ```),
inline code, blockquotes, ordered/unordered lists, footnotes via
<sup>, definition lists, and basic GFM extensions. Things it does
not handle: math (MathML/KaTeX rendered output), embedded SVG (stripped
by default via strip_tags), highly custom shortcode renderings.
Use GitHub Security Advisories (private): https://github.com/mhupfauer/caddy-md4agents/security/advisories/new. Don't open a public issue for security findings.
Docs
Reports