Open-Source Wikis

/

Caddy

/

Features

/

Caddyfile

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.Unmarshaler to be Caddyfile-friendly. Most do.
  • CLI: caddy adapt, caddy fmt, caddy validate all 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's UnmarshalCaddyfile.
  • Tweak global options: caddyconfig/httpcaddyfile/options.go.
  • Change caddy fmt behavior: caddyconfig/caddyfile/formatter.go.
  • Add a new adapter (NGINX, etc.): a separate Go module that calls caddyconfig.RegisterAdapter.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Caddyfile – Caddy wiki | Factory