caddyserver/caddy
Caddyfile
The Caddyfile is Caddy's human-friendly config language. It is parsed by caddyconfig/caddyfile/ and converted to JSON for the HTTP app by caddyconfig/httpcaddyfile/. The HTTP-Caddyfile adapter is the largest single subsystem in caddyconfig/ and httpcaddyfile/httptype.go (~61 KB) is its central file.
Purpose
Let users write configs that look like this:
example.com {
encode gzip
file_server
}
api.example.com {
reverse_proxy localhost:8080 {
health_path /healthz
}
}…and have Caddy turn them into the JSON the runtime actually consumes.
Directory layout
| Path | Role |
|---|---|
caddyconfig/caddyfile/lexer.go |
Token scanner (~11 KB) |
caddyconfig/caddyfile/parse.go |
Parser, ServerBlock, Token (~24 KB) |
caddyconfig/caddyfile/dispenser.go |
Token-stream API used by directive UnmarshalCaddyfile methods (~16 KB) |
caddyconfig/caddyfile/formatter.go |
caddy fmt implementation |
caddyconfig/caddyfile/adapter.go |
The generic Caddyfile adapter (used as a fallback when no app-specific adapter is configured) |
caddyconfig/caddyfile/importargs.go, importgraph.go |
import directive handling and cycle detection |
caddyconfig/httpcaddyfile/httptype.go |
The HTTP-app adapter (~61 KB) — the heavyweight glue from Caddyfile to JSON |
caddyconfig/httpcaddyfile/directives.go |
Registered directive list and ordering |
caddyconfig/httpcaddyfile/builtins.go |
Adapters for built-in directives like bind, tls, log (~35 KB) |
caddyconfig/httpcaddyfile/options.go |
Global options ({ … }) (~17 KB) |
caddyconfig/httpcaddyfile/serveroptions.go |
Per-server options |
caddyconfig/httpcaddyfile/shorthands.go |
Caddyfile-only shorthands |
caddyconfig/httpcaddyfile/addresses.go |
Site-block address parsing |
caddyconfig/httpcaddyfile/tlsapp.go |
Builds the tls JSON from tls/acme_*/local_certs directives (~42 KB) |
caddyconfig/httpcaddyfile/pkiapp.go |
Builds the pki JSON when needed |
Key abstractions
| Type | Where | Description |
|---|---|---|
Token |
caddyfile/parse.go |
One token: file, line, value |
ServerBlock |
caddyfile/parse.go |
Address keys + segments of directive tokens |
Dispenser |
caddyfile/dispenser.go |
Iterator/parser API directives use to consume their own tokens |
Helper (HTTP adapter) |
httpcaddyfile/httptype.go |
Per-directive helper struct with placeholders, options, and segment parsing |
Directive registration |
httpcaddyfile/directives.go |
Directive name → unmarshaler function + ordering |
How it works
graph TD
Source[Caddyfile text] -->|Lex| Tokens[token stream]
Tokens -->|Parse| Blocks[ServerBlock list]
Blocks --> Imports[expand import directives]
Imports --> Adapter[HTTP Caddyfile adapter]
Adapter -->|each directive| Unmarshal[directive UnmarshalCaddyfile]
Adapter -->|order by directives.go| Routes
Routes --> JSON[Caddy JSON]
JSON --> Runtime[caddy.Load]Lexer
lexer.go tokenizes the input, handling:
- Block delimiters
{ }. - Quoted strings with escape sequences.
- Heredocs (
<<TAG ... TAG). - Line continuations with
\. - Backtick-delimited "raw" strings.
- Comments (
#to end of line).
Parser
parse.go consumes tokens and produces ServerBlocks, each of which has:
- A list of address strings (the keys of the block).
- A list of "segments" — flat lists of tokens, each segment representing one directive invocation.
The parser is recursive-descent and tracks brace nesting. It resolves import directives by reading the imported file (or glob pattern), expanding placeholders for {args.*}, and splicing the tokens in. importgraph.go detects cycles.
Dispenser
dispenser.go is the API every directive uses to consume its own tokens. Directives implement:
func (m *MyMod) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
d.Next() // current token = directive name
for d.NextArg() { ... } // inline args
for nesting := d.Nesting(); d.NextBlock(nesting); { ... } // block body
}The Dispenser tracks position so d.Errf("…") produces file:line: … errors. Many directive parsers throughout modules/caddyhttp/* use the same pattern.
Directive registration and ordering
httpcaddyfile/directives.go registers every HTTP directive with a priority and an unmarshal function. The adapter then runs each directive's parser against the tokens and produces JSON fragments. The fragments are sorted into a single route list using the registered priorities (e.g. redir runs before respond, reverse_proxy runs after header, etc.).
That ordering is what makes the Caddyfile feel forgiving — you can put directives in any order in the file and the adapter still produces a sane route list.
Global options
{
debug
http_port 8080
https_port 8443
auto_https off
storage file_system { root /data/caddy }
log default { output file /var/log/caddy.log }
}Parsed by options.go. Each option has its own subparser; together they fill in Config.Admin, Config.Logging, Config.StorageRaw, plus auto-HTTPS toggles and per-server options.
TLS and PKI apps
tlsapp.go (~42 KB) and pkiapp.go synthesize the tls and pki apps from Caddyfile directives like tls, acme_dns, acme_eab, local_certs, pki. Most users never write these explicitly — they appear automatically when a site uses HTTPS.
Other adapters
caddyconfig/configadapters.go is the registry. Adapter modules implement:
type Adapter interface {
Adapt(body []byte, options map[string]any) ([]byte, []Warning, error)
}The Caddyfile adapter is one; community plugins ship NGINX, JSON 5, YAML, TOML adapters following the same interface.
caddyconfig/load.go is what caddy run --config and the /load admin endpoint use to detect and apply an adapter.
caddyconfig/httploader.go implements an HTTP loader that fetches config from a URL — the underlying mechanism for caddy.config_loaders.http.
Integration points
- HTTP app: the largest consumer; the Caddyfile is essentially an HTTP-app DSL.
- Modules: any handler/matcher module can implement
caddyfile.Unmarshalerto be Caddyfile-friendly. Most do. - CLI:
caddy adapt,caddy fmt,caddy validateall run through the same parser/adapter chain.
Entry points for modification
- Add a new directive: register it in
caddyconfig/httpcaddyfile/directives.go(with a priority), implement an unmarshal function, and add the module'sUnmarshalCaddyfile. - Tweak global options:
caddyconfig/httpcaddyfile/options.go. - Change
caddy fmtbehavior:caddyconfig/caddyfile/formatter.go. - Add a new adapter (NGINX, etc.): a separate Go module that calls
caddyconfig.RegisterAdapter.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.