caddyserver/caddy
Fun facts
A handful of trivia about this repo, collected from git log, the source tree, and the README.
The name
The name "Caddy" was chosen because this software helps with the tedious, mundane tasks of serving the Web, and is also a single place for multiple things to be organized together.
—
README.md
The README also notes that "Caddy" is a registered trademark and explicitly asks you not to call it "Caddy Server" or "CaddyServer".
The first commits
The first three commits of the v2 repo all happened on March 26, 2019, and they read like a TODO list:
859b5d7e Initial commit
86e2d1b0 Rudimentary start of HTTP servers
a8dc73b4 Performance testing Load functionEvery modern Caddy run still passes through the descendant of that third commit's Load function (now in caddy.go).
The largest file
The biggest single Go file in the production tree is modules/caddyhttp/reverseproxy/reverseproxy.go at ~68 KB. The runner-up is caddyconfig/httpcaddyfile/httptype.go at ~61 KB — that's the Caddyfile→JSON glue for the HTTP app, and it carries the directive-ordering logic that gives the Caddyfile its forgiving syntax.
The "everything is a module" rule
A lot of things you would not expect to be modules are, in fact, modules:
- The default file-system storage is
caddy.storage.file_system(modules/filestorage/). - The standard streams
stdoutandstderrare log writerscaddy.logging.writers.stdout/caddy.logging.writers.stderr(logging.go). - The DNS provider for "I have no DNS provider" is
dns.providers.mock(used in tests,caddytest/integration/mockdns_test.go). - Even the network proxy "no proxy" mode is a module:
caddy.network_proxy.none.
If something feels like it should have been a flag, look for a module first.
The hidden CEL engine
modules/caddyhttp/celmatcher.go (~29 KB) embeds Google's CEL expression language so you can write request matchers like:
@admins expression `header("X-Role") == "admin" && path.startsWith("/api/")`It is one of the few places in the codebase where Caddy uses a full programming-language interpreter instead of a hand-rolled DSL.
The pingback trick
caddy start spawns a background Caddy process and waits for it to come up. To distinguish "the server printed a startup banner" from "the server is actually serving", the parent generates 32 random bytes and listens on a localhost socket. The child connects to that socket and writes the same bytes back; only then does caddy start exit. The handshake helper is handlePingbackConn in cmd/main.go.
ACME, agreed
In cmd/main.go's init():
// by using Caddy, user indicates agreement to CA terms
// (very important, as Caddy is often non-interactive
// and thus ACME account creation will fail!)
certmagic.DefaultACME.Agreed = trueThat comment is the only place in the codebase where the project tells you, with feeling, why something must be true.
Module IDs in the wild
Counting unique module IDs across the standard build (via grep -h 'ID:.*"' --include="*.go" -r) yields about 145 distinct identifiers, dominated by the http.* (64) and 32) namespaces. That is more or less a measure of "how many things you can plug in or swap out without recompiling" — except, of course, that you do recompile, because Caddy plugins are statically linked.tls.* (
Cross-platform quirks
The repo has separate listeners for some kernel features:
listen_unix.go/listen_unix_setopt.go— Unix sockets andSO_REUSEPORT.listen_unix_setopt_freebsd.go— FreeBSD has a different name for the same option.listen_reuseUnixSocket.go/listen_reuseUnixSocket_windows.go— graceful Unix-socket reuse during reload, with a separate Windows implementation that can't actually reuse them.
Those tiny build-tagged files are a quiet reminder that "runs anywhere" requires real per-OS code.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.