Open-Source Wikis

/

Caddy

/

Fun facts

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 function

Every 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 stdout and stderr are log writers caddy.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 = true

That 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 tls.* (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.

Cross-platform quirks

The repo has separate listeners for some kernel features:

  • listen_unix.go / listen_unix_setopt.go — Unix sockets and SO_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.

Fun facts – Caddy wiki | Factory