Open-Source Wikis

/

Caddy

/

Caddy

/

Getting started

caddyserver/caddy

Getting started

This page covers building Caddy from source, running it, and writing a first Caddyfile. The canonical user-facing docs live at caddyserver.com/docs — the goal here is to get you running locally so you can hack on the codebase.

Prerequisites

  • Go 1.25.0 or newer. The repo's go.mod pins go 1.25.0. CI runs against Go 1.26 (.github/workflows/ci.yml).
  • golangci-lint for linting (.golangci.yml configures the rules; CI uses golangci-lint run --timeout 10m).
  • xcaddy is optional but required to embed plugins or to build with proper version metadata. See https://github.com/caddyserver/xcaddy.

Build the binary

git clone https://github.com/caddyserver/caddy.git
cd caddy/cmd/caddy
go build

That produces a caddy binary in cmd/caddy/. The CI pipeline uses the same path with extra flags:

cd cmd/caddy
CGO_ENABLED=0 go build -trimpath -ldflags="-w -s" -v

If you want plugin support and accurate version strings, use xcaddy build instead. Internally xcaddy writes a tiny main.go that imports plugins and runs go build.

Bind to low ports (Linux)

If you run Caddy as a non-root user on Linux and bind to ports 80/443, you need the cap_net_bind_service capability:

sudo setcap cap_net_bind_service=+ep ./caddy

For go run workflows, the repo includes a helper at cmd/caddy/setcap.sh:

go run -exec ./setcap.sh main.go

Run a hello-world site

Save this as Caddyfile:

:8080
respond "hello, world"

Then run:

./caddy run --config Caddyfile
curl -i http://localhost:8080/

You should see hello, world. Behind the scenes, caddy run (cmd/commands.go) loads the file, runs it through the caddyfile adapter (caddyconfig/httpcaddyfile/), POSTs the resulting JSON to the local admin endpoint via caddy.Load, and starts the http app.

Inspect the generated JSON

./caddy adapt --config Caddyfile --pretty

caddy adapt invokes the named adapter and prints the JSON document Caddy would actually run. This is the single best learning tool: every Caddyfile concept reduces to JSON.

Reload without restarting

./caddy reload --config Caddyfile

caddy reload re-reads the config file and posts it to the admin API (/load). Caddy provisions the new config, swaps it in under a mutex, and rolls back if anything fails (Load in caddy.go).

You can do the same thing manually:

curl -X POST -H "Content-Type: application/json" \
  --data-binary @config.json \
  http://localhost:2019/load

Run the test suite

The repo's quality gates are:

# Unit tests with the race detector (matches CI)
go test -race -short ./...

# Integration tests
go test ./caddytest/integration/...

# Lint
golangci-lint run --timeout 10m

The integration harness lives in caddytest/caddytest.go. Tests pull non-default ports (9080, 9443, 2999) so they do not conflict with a real Caddy you may have running.

Where to look next

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

Getting started – Caddy wiki | Factory