mrkeyoor.com_
Wed 16 Sept 09:12 UTC
Dev Toolsevaluationupdated 27 Aug 2026

caddy review

Caddy is a web server and reverse proxy that obtains and renews TLS certificates automatically. It gives small sites a short Caddyfile, while larger systems can use native JSON, an admin API, and compiled Go modules.

+169stars / 7d
Verdict

Our Caddy build succeeded in 114 seconds, but the 78-second test run ended with 21 package results passing and 1 failing, so contributors should reproduce the failing package before shipping a custom binary. For a small website or self-hosted reverse proxy, Caddy's automatic HTTPS and concise configuration make it one of the easiest serious options to operate. Test protocol-specific upstream paths, persist certificate state, and treat every plugin build as its own release artifact.

We ran it

Lab card: what happened when we ran caddyScreenshot of caddy (caddyserver.com)
Install✓ · 86s553 packages
Build✓ · 114s
Tests✗ · 78s21 passed · 1 failed of 22 (go test)
Repo655 files~105,022 lines of source · 4.3 MB · 9 CI workflows

Answers from our run

Does caddy build from source?

Dependencies installed in 86 seconds (553 packages), and the build succeeded in 114 seconds. We cloned commit 0cf03d3 into a clean Debian container with 3 CPUs and no project-specific setup.

Do caddy's tests pass?

Not all of them: 21 of 22 passed and 1 failed when we ran the project's own test command (go test). Some failures need services or credentials a bare container does not have.

Who should not use caddy?

Operators who require runtime-loaded plugins: the README's supported plugin path uses xcaddy to compile modules into a new binary.

What are the alternatives to caddy?

NGINX, Traefik, HAProxy. Our Caddy build succeeded in 114 seconds, but the 78-second test run ended with 21 package results passing and 1 failing, so contributors should reproduce the failing package before shipping a custom binary.

Setup4/5The build passed; one of 22 package test results failed
Docs5/5Caddyfile, JSON, API, HTTPS, and plugin paths are documented
Community5/575,237 stars with active August 2026 development
Maturity5/5v2.11.4 ships signed fixes for mature server paths

Discussed on

  1. hnCaddy Proposal: Permanently change all proprietary licensing to open source357 points
  2. hnCaddyhttp: Enable HTTP/3 by Default284 points
  3. hnShow HN: Caddy v2.5.0269 points
  4. hnCaddy 2.8179 points
  5. hnCaddy 2.6 is out, the biggest release since Caddy 256 points

Who it’s for

Developers who want HTTPS defaults without writing certificate automation.
Self-hosters putting a readable reverse-proxy configuration in front of several services.
Platform teams that want live configuration through a JSON API.
Go developers willing to compile required plugins into a custom Caddy binary.

Who it’s NOT for

Operators who require runtime-loaded plugins: the README's supported plugin path uses xcaddy to compile modules into a new binary.
Teams unwilling to give the process access to low ports or place another listener in front: the source-build guide notes that ports such as 80 and 443 may need extra privileges.
Buyers who assume automatic HTTPS removes DNS and reachability work: certificate issuance still depends on valid names and ACME challenge access.
Deployments using HTTP/3 clients with strict HTTP/2 upstreams without testing: issue 7835 reports bodyless requests producing 502 responses on v2.11.4 in that path.
Companies that require vendor support bundled with the software: the README points commercial users to a separate support contract.

Setup reality

Our sandbox installed 553 Go packages in 86 seconds, then built Caddy successfully in 114 seconds. Tests failed after 78 seconds: 21 package results passed and 1 failed out of 22. The supplied log tail ends with FAIL but does not identify the failing package or cause.

The stock binary needs a Caddyfile or JSON config, reachable DNS for public certificates, and permission to bind the chosen ports. Production should persist Caddy's data directory so certificate state survives restarts.

Custom plugins require a separately built binary through xcaddy; they are not added to a running process. The admin API changes live configuration and should stay on a protected interface. Container users must mount both configuration and state deliberately.

Automatic HTTPS removes certificate plumbing, not DNS work

Caddy's best feature is easy to explain: give it a public hostname and a handler, and it can obtain a certificate, redirect HTTP to HTTPS, serve modern protocols, renew the certificate, and keep the site running through routine renewal work. A basic reverse proxy can fit in a few Caddyfile lines. That is a meaningful reduction in configuration for personal servers and small production services.

The automation still has prerequisites. Public DNS must point to the server, the relevant ACME challenge must reach it, and Caddy needs persistent writable storage for account and certificate material. Low ports such as 80 and 443 may require capabilities or a privileged listener arrangement. If a firewall, load balancer, or container mapping blocks the challenge, automatic HTTPS has no way to repair the surrounding network.

The Caddyfile stays readable until JSON is the better interface

The Caddyfile is an adapter rather than Caddy's native configuration format. It is pleasant for common static sites, reverse proxies, redirects, headers, and encoders. Caddy converts it into JSON, which maps more directly to loaded modules and routes. Operators can inspect the adapted output before deployment instead of guessing how shorthand expands.

Larger installations may prefer the JSON API because it can change a running configuration without restarting the process. That power creates another security boundary: an exposed admin endpoint can alter the server. Keep it on a protected interface, authenticate any remote control layer, and store the intended configuration in version control. A live API is useful only when the team can also reproduce and audit its state.

What happened when we ran it

Our sandbox installed 553 Go packages in 86 seconds. The build then succeeded in 114 seconds on commit 0cf03d3, using an unprivileged Debian container with 3 CPUs and 8 GB of RAM. The source checkout contained 655 files, about 105,022 lines, and occupied 4.3 MB. Nine CI workflow files were present, while the scanner found no Dockerfile or top-level tests directory.

The Go test run failed with exit code 1 after 78 seconds. It reported 21 package results as passed and 1 as failed out of 22. The supplied final lines show successful results for caddypki, caddytls, filestorage, internal networking, logging, and metrics before the overall FAIL. They do not show the failing package or its error, so we cannot assign a cause from this evidence.

A successful 114-second compile proves that the checked-out source could produce a binary in our environment. The failed suite prevents a clean contributor result. Before distributing a custom build, rerun the suite with full logs, isolate the failing package, and record the exact Go environment. Users installing the official v2.11.4 binary are taking a different path from our source checkout.

Plugins become part of your binary

Caddy's module system covers handlers, storage, authentication, DNS providers, and configuration adapters. The supported custom-build workflow uses xcaddy: it creates a Go module, pins a Caddy version if requested, imports selected plugins, and compiles a new executable. This produces a clean deployment unit with no runtime plugin directory. It also makes the operator responsible for that exact dependency set.

Every plugin changes the artifact you patch and test. A stock release update does not automatically rebuild a private combination, and a module can carry its own configuration or maintenance risks. Keep the xcaddy inputs pinned, generate a repeatable binary, retain its version metadata, and run configuration plus request tests against the result. If standard Caddy covers the job, the official binary is the simpler choice.

HTTP/3 and strict upstreams need a representative test

Caddy supports HTTP/1.1, HTTP/2, and HTTP/3 by default, which is useful when clients and upstreams vary. Protocol translation also creates unusual corners. Open issue 7835 reports that a bodyless HTTP/3 request proxied to a strict HTTP/2 upstream can arrive with an indeterminate content length and receive a 502. The reporter reproduced it on v2.11.4 and listed forcing HTTP/1.1 upstream or disabling HTTP/3 as workarounds.

That issue should not scare a normal HTTP/1.1 backend deployment away. It should change the acceptance test for IIS or another strict HTTP/2 upstream. Send real browser traffic over each enabled client protocol, verify headers and bodies at the backend, and test failure responses. Open issue 7225 likewise reports proxy-placeholder trouble in a particular HTTP proxy path. These are narrow, citable reasons to test the topology you will actually run.

June security fixes make current patching important

GitHub showed 75,237 stars and 266 combined issues and pull requests when fetched. The last source push was August 25, 2026. Release v2.11.4 arrived on June 3 with fixes for Windows backslashes in path matching, query placeholder re-expansion, malformed HTML stripping, header-name collisions, TLS state races, and reverse-proxy request handling. The notes warn that some security fixes can break configurations that depended on earlier behavior.

That is healthy maintenance and a reminder to stage upgrades. Validate the Caddyfile or JSON, exercise certificate issuance in a safe environment, and send representative proxy requests before replacing the production binary. Caddy earns its place by making the common secure path short. It does not excuse careless admin-API exposure, untracked plugin builds, missing state volumes, or skipped regression tests.

Alternatives

ProjectWhat it isPick it when
NGINX gh↗A widely deployed web server and reverse proxy with a large operations ecosystem.pick this instead when existing NGINX expertise and its configuration model outweigh built-in certificate automation.
Traefik gh↗A reverse proxy centered on dynamic service discovery and container platforms.pick this instead when Docker or Kubernetes discovery should drive routes automatically.
HAProxyA proxy and load balancer with deep traffic-control and observability options.pick this instead when advanced load balancing is the main job and certificates are managed elsewhere.

What people are saying

  1. [github-trending] caddyserver/caddy

Sources

  1. Caddy repository
  2. Caddy v2.11.4 release
  3. Caddy documentation
  4. Caddy admin API documentation
  5. HTTP/3 to HTTP/2 proxy regression issue
  6. HTTP proxy placeholder issue

More dev tools reviews

IKONA-Security · noty · forward-implementation-first · breakscale · black · ASC · the whole board →