Releases: caddyserver/caddy
v2.10.0-beta.4
Welcome to the pre-release versions for Caddy 2.10! We hope you will try these betas in your production environments after verifying them in testing/staging, and offer your feedback so the stable release will be better.
We're excited for 2.10, as it will bring many improvements, new features, and fixes to your web server. Expect several beta versions as we work through a backlog of issues and pull requests.
Aside from many bug fixes, this beta already features:
- Encrypted ClientHello (ECH): The draft spec for ECH is almost finalized, so we can now support this privacy feature for TLS. This is a powerful but nuanced capability; see below (and docs on the website) for details.
- Post-quantum (PQC) key exchange: Caddy now supports the standardized
x25519mlkem768
cryptographic group by default. - ACME profiles: ACME profiles are an experimental draft that allow you to choose properties of your certificates with more flexibility than traditional CSR methods. For example, Let's Encrypt will issue 6-day certificates under a certain profile. Caddy may eventually use that profile by default.
- Via header: The reverse proxy now sets a Via header instead of a duplicate Server header.
- Global DNS provider: You can now specify a default "global" DNS module to use instead of having to configure it locally in every part of your config that requires a DNS provider (for example, ACME DNS challenges, and ECH). This is the
dns
global option in the Caddyfile, or in JSON config, it's thedns
parameter in thetls
app configuration.
Encrypted ClientHello (ECH) details
Typically, server names (domain names, or "SNI") are sent in the plaintext ClientHello when establishing TLS connections. With ECH, the true server name is encrypted (and wrapped) by an "outer" ClientHello which has a generic SNI of your choosing. With many sites on the same server sharing the same outer SNI, both clients and the server have more privacy relative to domain names.
Caddy implements fully automated ECH, meaning that it generates (and soon, rotates), publishes, and serves ECH configurations simply by specifying a DNS provider, and the outer/public domain name to use.
Fully automated ECH requires a DNS module built into your Caddy binary. In order for a client, such as a browser, to know it can use ECH, and what parameters to use, the server's ECH configuration must be published. This config includes the public name, cryptographic parameters, and a public key for encrypting the inner ClientHello. By convention, browsers read the standardized HTTPS-type DNS record containing a ech
SvcParamKey. Caddy sets this DNS record for all domains being protected, but it needs that DNS provider module plugged in and configured in order to do this. If you are already using the DNS ACME challenge, you should already have a DNS provider plugged in. If you prefer to build Caddy from source with a DNS module, it's easy with xcaddy, for example: $ xcaddy build --with github.com/caddy-dns/cloudflare
The minimum config needed to enable ClientHello is also the recommended config, as it maximizes privacy benefits in most situations. You just need the ech
global option and a DNS provider specified. Here's an example using Cloudflare as the nameserver:
Caddyfile:
{
debug # not required; recommended while testing
dns cloudflare {env.CLOUDFLARE_API_KEY}
ech ech.example.net
}
example.com {
respond "Hello there!"
}
This protects all your sites (example.com
in this case) behind the public name of ech.example.net
. (As another example, Cloudflare uses cloudflare-ech.com
for all the sites it serves. We recommend choosing a single public domain and use it to protect all your sites.)
The outer/public name you choose should point to your server. Caddy will obtain a certificate for this name in order to facilitate safe, reliable connections for clients when needed. Without a certificate, clients may be forced to connect insecurely, or fail to connect at all, in some cases, which not only leaves them vulnerable, but also risks exposing the names of your server's sites.
Caddy then uses the specified DNS provider to publish the ECH config(s) for your various site names. It creates (or augments) HTTPS-type records for the domains of your sites (not your ECH public name). Note that DNS provider modules are independently-maintained, and may not have been tested for compatibility with HTTPS-type records. Please contact your module's maintainers if you experience issues.
If you have more advanced configuration needs, you can use the JSON configuration (more details coming soon; for now, see #6862 or look at the source code; or use caddy adapt
to convert a Caddyfile to JSON).
Testing and verifying Encrypted ClientHello
First make sure Caddy runs successfully with ECH enabled (and a DNS module) in the config. You should see logs that it is generating an ECH config and publishing it to your domain name(s).
You will need to use a client that supports ECH. Some custom builds of curl
do, and Firefox and modern Chrome-based browsers do as well, but you need to enable DNS-over-HTTPS or DNS-over-TLS first (since, obviously, querying DNS in plaintext for a protected domain name will expose the domain and defeat the purpose of ECH).
If reusing an existing domain name, clear your DNS cache. Firefox has a way of doing this for its cache at about:networking#dns
.
Once you have a suitable client, use Wireshark to capture network packets as you load your site. You should see only the outer/public name as SNI (ServerName Indicator) values in the packet capture. If at any time you see the true site name, ECH is not working properly -- it could be a client or server issue. Before filing a bug, please try to pinpoint it as a server issue first. But definitely report server bugs! Thank you!
(Note that ECH is not automatically published for CNAME'd domains, and the domain must already have a record in the zone.)
Commits
Beta 1:
- 96c5c55 admin: fix index validation for PUT requests (#6824)
- 3644ee3 build(deps): bump github.com/cloudflare/circl from 1.3.3 to 1.3.7 (#6876)
- eacd772 build(deps): bump github.com/go-jose/go-jose/v3 from 3.0.3 to 3.0.4 (#6871)
- 9996d6a build(deps): bump github.com/golang/glog from 1.2.2 to 1.2.4 (#6814)
- 1115158 caddyhttp: ResponseRecorder sets stream regardless of 1xx
- 8861eae caddytest: Support configuration defaults override (#6850)
- d7764df caddytls: Encrypted ClientHello (ECH) (#6862)
- a807fe0 caddytls: Enhance ECH documentation
- bc3d497 caddytls: Fix broken refactor
- 7b8f350 caddytls: Fix sni_regexp matcher to obtain layer4 contexts (#6804)
- 2c4295e caddytls: Initial support for ACME profiles
- d7872c3 caddytls: Refactor sni matcher (#6812)
- 172136a caddytls: Support post-quantum key exchange mechanism X25519MLKEM768
- 066d770 cmd: automatically set GOMEMLIMIT (#6809)
- 1f35a8a fastcgi: improve parsePHPFastCGI docs (#6779)
- 22563a7 file_server: use the UTC timezone for modified time (#6830)
- cfc3af6 fix: update broken link to Ardan Labs (#6800)
- 99073ea go.mod: Upgrade CertMagic to v0.21.7
- 1641e76 go.mod: Upgrade dependencies
- 0d7c639 go.mod: remove glog dependency (#6838)
- 932dac1 logging: Always set fields func; fix #6829
- 9e0e5a4 logging: Fix crash if logging error is not HandlerError (#6777)
- 904a0fa reverse_proxy: re-add healthy upstreams metric (#6806)
- e7da3b2 reverseproxy: Via header (#6275)
- 9283770 reverseproxy: ignore duplicate collector registration error (#6820)
Beta 2:
- f4432a3 caddyfile: add error handling for unrecognized subdirective/options in various modules (#6884)
- 84364ff caddypki: Remove lifetime check at Caddyfile parse (fix #6878)
- adbe7f8 caddytls: Only make DNS solver if not already set (fix #6880)
- d57ab21 caddytls: Pointer receiver (fix #6885)
- 4ebcfed caddytls: Reorder provisioning steps (fix #6877)
- a686f7c cmd: Only set memory/CPU limits on run (fix #6879)
- 1987620 cmd: Promote undo maxProcs func to caller
- 220cd1c reverseproxy: more comments abou...
v2.10.0-beta.3
This prerelease is outdated. Please see the latest release for notes and a hotfix for a regression. Thanks!
v2.10.0-beta.2
This prerelease is outdated. Please see the latest release for notes. Thanks!
v2.10.0-beta.1
This prerelease is outdated. Please see the latest release for notes. Thanks!
v2.9.1
This is a patch release fixing a few issues related to FastCGI, HTTP/3 and unix sockets, log file permissions, repeated TERM signals, and an ARI edge case. It also adds Caddyfile support for response matching in the header
directive.
Thanks to everyone who reported bugs and helped with fixes!
Changelog
- 34cff4a core: Only initiate exit once (should fix #6707)
- 50778b5 fix: disable h3 for unix domain socket (#6769)
- 0e570e0 go.mod: Upgrade CertMagic to 0.21.6 (fix ARI handshake maintenance)
- e48b758 header:
match
subdirective for response matching (#6765) - 1f927d6 log: Only chmod if permission bits differ; make log dir (#6761)
- 1bd567d reverseproxy: buffer requests for fastcgi by default (#6759)
What's Changed
- reverse proxy: fastcgi buffer requests for fastcgi by default by @WeidiDeng in #6759
- fix: disable h3 for unix domain socket by @Geun-Oh in #6769
- log: Only chmod if permission bits differ by @mholt in #6761
- header:
match
subdirective for response matching by @lilnasy in #6765
New Contributors
Full Changelog: v2.9.0...v2.9.1
v2.9.0
Happy New Year! We're pleased to release Caddy 2.9. Aside from some minor new features, this release is mainly focused on refinements and bug fixes in many areas, including:
- Config loading
- Events
- Logging
- Placeholders
- Reverse proxy and HTTP server performance
- Matchers
- HTTP (esp. HTTP/3)
- Metrics (per-host metrics)
- Security
- TLS automation & ACME ARI
We realize there is extensive interest in Encrypted Client Hello (ECH) and post-quantum ciphers. These are slated to be supported in Go 1.24, which is scheduled for a stable release in approximately February. We did not want to force users to go through the inconvenience of installing pre-release, non-stock installations of Go, even though the RCs are quite stable and production-ready, in order to even compile Caddy, which is quite common given our plugin ecosystem. We anticipate a Caddy 2.10 release in the near future with these capabilities, built on Go 1.24.
We hope you will enjoy the 2.9 release. Thanks to all contributors, bug reporters, and helpers, and those organizations which deployed pre-release versions to production to help verify patches and features.
Changelog
- ef4e022 caddyfile: Fix comma edgecase in address parsing (#6616)
- b116dce caddyhttp: Add
{?query}
placeholder (#6714) - c216cf5 caddyhttp: Allow matching Transfer-Encoding, add to access logs (#6629)
- 197c564 caddyhttp: Set default ReadHeaderTimeout (1 min)
- 09b2cbc caddyhttp: Add
MatchWithError
to replace SetVar hack (#6596) - c6f2979 caddyhttp: Close http3 server gracefully (#6213)
- 88fd5f3 caddyhttp: Use internal issuer for IPs when no APs configured
- 5c8dc34 caddytls: Allow disabling storage cleaning, avoids writing two files (#6593)
- d7564d6 caddytls: Drop
rate_limit
andburst
, has been deprecated (#6611) - d398898 cmd: Allow
add-package
to select version of package (#6665) - 66c80ca cmd: Disable go1.23 tlskyber=1 experiment
- fb72793 cmd: Reject multiple configs for fmt command (#6717)
- b3ce260 cmd: ignore missing keys during storage export (#6697)
- 0182fb8 core: addresses.go funcs renames (#6622)
- e76405d core: Change ListenerFunc signature (#6651)
- 315715e core: Implement FastAbs to avoid repeated os.Getwd calls (#6687)
- d0e209e encode: good defaults (#6737)
- 5ba1e06 encode: try to use sendfile when compression is not used (#6749)
- bcaa8aa encode: write status immediate for success response for CONNECT requests (#6738)
- 1d15652 events: Use
WithLazy
to prevent eager serialization of the event data (#6671) - 6790c0e fastcgi: check for CONTENT_LENGTH when sending requests (#6661)
- eddbccd fastcgi: remove dir redirection when useless in php_fastcgi (#6698)
- efd9251 fileserver: Add
first_exist_fallback
strategy fortry_files
(#6699) - d0123bd fileserver: Fix policy
Validate()
oversight (#6727) - 290cfea fileserver: add a test for precompressed defaults (#6743)
- 5c2617e fileserver: good default for precompressed (#6736)
- cc23ad6 fileserver: Add
file_limit
option for browse (to be experimental) (#6648) - 350ad38 fileserver: Fix Caddyfile parsing
- 9753c44 fileserver: fix try_policy when instantiating file matcher from CEL (#6624)
- 05cfb12 forwardauth: Skip copying missing response headers (#6608)
- ed1c594 go.mod: Upgrade ACMEz to v3; and upgrade CertMagic
- 3f3f8b3 go.mod: Upgrade CertMagic to v0.21.5
- 91e3413 go.mod: upgrade only some otel deps (#6676)
- 22b9d51 go.mod: Upgrade quic-go to 0.48.2
- b129ed6 httpcaddyfile: Fixes for
prefer_wildcard
mode (#6636) - afa778a httpcaddyfile: Implement experimental
force_automate
option (#6712) - b183aec httpcaddyfile: Implement log
sampling
config (#6682) - 1d106fa metrics: add
go
andprocess
collectors (#6704) - 388c7e8 metrics: move
metrics
up, outsideservers
(#6606) - 8c3dd3d requestbody: Type-based error handling for
MaxBytesError
(#6701) - 5e6024c reverseproxy: Fix log message
- 48ce47f reverseproxy: Use correct cases for websocket related headers (#6621)
- 825fe48 reverseproxy: Allow
0
as weights forweighted_round_robin
(#6681) - 328fb61 reverseproxy: Only handle websocket protocol (#6740)
- 238f110 reverseproxy: Revert #4952 - don't ignore context cancellation in stream mode
- 9c0c71e reverseproxy: Rewrite requests and responses for websocket over http2 (#6567)
- c864b82 reverseproxy: Set Content-Length when body is fully buffered (#6638)
- fbf0f4c reverseproxy: Sync changes from stdlib for 1xx handling (#6656)
- 5823ecc rewrite: Don't add / in Caddyfile, do it after replacer (#6662)
- b443190 sigtrap: always ignore SIGPIPE (#6645)
- f2c17d1 testing: sort force-automated hosts (#6756)
- 669fc41 tracing: Add
spanID
field to access logs andhttp.vars.span_id
placeholder (#6646)
What's Changed
- Make it possible to configure the
DisableStorageCheck
setting for certmagic by @ankon in #6368 - caddyhttp: Add test case to corpus by @mholt in #6374
- cmd: remove zealous check of Caddyfile auto-detection by @mohammed90 in #6370
- ci: upgrade to goreleaser v2 by @mohammed90 in #6376
- logging: Allow setting log file permissions by @ririsoft in #6314
- Split
run
into a publicBuildContext
and a private part by @ankon in #6378 - Write the header if none had been written in WriteResponse by @ankon in #6380
- fix file mode configuration parsing by @ririsoft in #6383
- go.mod: update tscert package by @willnorris in #6384
- logging: Customizable
zapcore.Core
by @kkroo in #6381 - logging: set file mode when the file already exist. by @ririsoft in #6391
- caddyfile: Pass blocks to
import
for snippets by @elee1766 in #6130 - reverseproxy: add Max-Age option to sticky cookie by @JasonYuan869 in #6398
- fileserver: Remove newline characters from precomputed etags by @armadi1809 in #6394
- fix: http.intercept.header.* placeholders by @dunglas in #6429
- reverseproxy: Only log host is up status on change by @klaxa in #6419
- fix: don't compress already compressed fonts by @dunglas in #6432
- caddyhttp: Reject 0-RTT early data in IP matchers and set Early-Data header when proxying by @mholt in #6427
- reverseproxy: Add placeholder for host in active health check headers by @francislavoie in #6440
- browse: add Content-Security-Policy w/ nonce by @steffenbusch in #6425
- browse: fix Content-Security-Policy warnings in Firefox by @steffenbusch in #6443
- fileserver: Exclude symlink target size from total, show arrow on size by @francislavoie in #6412
- reverseproxy: Fix dynamic upstreams ip version by @armadi1809 in #6448
- reverseproxy: Add placeholder for networkAddr in active health check headers by @dylanschultzie in #6450
- Add option to set which HTTP method to use for active health checks by @jbro in #6453
- reverseproxy: Caddyfile support for health_method by @jbro in #6454
- reverseproxy: add health_upstream subdirective by @dylanschultzie in #6451
- ci: correct
-tags nobadger
on binary build by @girlbossceo in #6470 - Caddyfile support for TLS handshake matchers by @vnxme in #6461
- Caddyfile suppor...
v2.9.0-beta.3
This release has been superseded by v2.9.0 stable.
v2.9.0-beta.2
This beta is outdated, please use the latest version.
v2.8.4
v2.8.2
A few more fixes of reported bugs related to ARI, try_files
with the root path (/
), and Caddyfile adapter detection on the CLI. See 2.8.0 release notes for details on 2.8.
Changelog
- 01308b4 I'm so tired of typos
- a63767d build(deps): bump golangci/golangci-lint-action from 5 to 6 (#6361)
- f8a2c60 caddyhttp: properly sanitize requests for root path (#6360)
- b7280e6 caddytls: Implement certmagic.RenewalInfoGetter
- 15faeac cmd: fix auto-detetction of .caddyfile extension (#6356)
Full Changelog: v2.8.1...v2.8.2