--- snapshot-1779709455+++ snapshot-1780472037@@ -2,7 +2,11 @@ Release notes from caddy -2026-05-12T02:55:07Z tag:github.com,2008:Repository/29207621/v2.11.3 2026-05-12T15:18:58Z +2026-06-03T03:54:40Z tag:github.com,2008:Repository/29207621/v2.11.4 2026-06-03T06:53:12Z + +v2.11.4 + +
This release patches more security, security-adjacent, and normal bugs. The FrankenPHP project has collaborated on PHP-adjacent patches, which we are grateful for.
The recent surge of patches is mostly attributed to token predictors. We have had to reject more than 75% of "security" reports because they were AI slop spam (or just lazy/incorrect). Please use LLMs and agents wisely to avoid wasting precious maintainer resources. We have started blocking offending accounts that spam slop reports. Thank you to all who submit responsible reports following our security policy to make the project better. We appreciate that the community deems the Caddy project worthy of contribution to improve the broader ecosystem!
Security-related patches:
stripHTML action to more reliably remove malformed HTML (thanks to @jmrcsnchz)There are also several other various fixes and enhancements by many other contributors. Thank you everyone who participated!
Full Changelog: v2.11.3...v2.11.4
github-actions[bot] tag:github.com,2008:Repository/29207621/v2.11.3 2026-05-12T15:18:58Z v2.11.3 @@ -38,8 +42,4 @@ v2.10.0 -Caddy 2.10 is here! Aside from bug fixes, this release features:
x25519mlkem768 cryptographic group by default.dns global option in the Caddyfile, or in JSON config, it's the dns parameter in the tls app configuration.tls force_automate in the Caddyfile. The experimental auto_https prefer_wildcard option has been removed.dns config: Now that several components of Caddy configuration may affect DNS records (ACME challenges, ECH publication, etc.), there is a new dns global option that can be used to specify your DNS provider config in a single place. This prevents repetition of credentials for servers where all the domains are managed by a single DNS provider.Thank you to the many contributors who have helped to make this possible! 🎉 🥳 🍾
(This is a brief overview. We recommend reading the full documentation.)
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 related 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).
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.)
network_proxy support (#6399)archives.format_overrides.format by @mohammed90 in #6807replace for optional body replacement by @AdrienPensart in #5795network_proxy support by @mohammed90 in #6399Full Changelog: v2.9.1...v2.10.0
github-actions[bot] tag:github.com,2008:Repository/29207621/v2.10.0-beta.4 2025-04-18T20:45:20Z - -v2.10.0-beta.4 - -This prerelease is outdated. Please see the latest release for notes. Thanks!
github-actions[bot]+Caddy 2.10 is here! Aside from bug fixes, this release features:
x25519mlkem768 cryptographic group by default.dns global option in the Caddyfile, or in JSON config, it's the dns parameter in the tls app configuration.tls force_automate in the Caddyfile. The experimental auto_https prefer_wildcard option has been removed.dns config: Now that several components of Caddy configuration may affect DNS records (ACME challenges, ECH publication, etc.), there is a new dns global option that can be used to specify your DNS provider config in a single place. This prevents repetition of credentials for servers where all the domains are managed by a single DNS provider.Thank you to the many contributors who have helped to make this possible! 🎉 🥳 🍾
(This is a brief overview. We recommend reading the full documentation.)
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 related 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).
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.)
network_proxy support (#6399)archives.format_overrides.format by @mohammed90 in #6807replace for optional body replacement by @AdrienPensart in #5795network_proxy support by @mohammed90 in #6399Full Changelog: v2.9.1...v2.10.0
github-actions[bot]