What’s New

Caddy

Developer Tools

HTTP/2 web server with automatic HTTPS and certificate management.

Latest v2.11.4 · by CaddyWebsitecaddyserver/caddy

Changelog

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:

  • caddyhttp: Normalize Windows backslashes in path matcher (thanks @Vincent550102)
  • rewrite: Prevent placeholder re-expansion in injected query (thanks @WhiskerEnt)
  • templates: Improved stripHTML action to more reliably remove malformed HTML (thanks to @jmrcsnchz)
  • caddyhttp: Ignore header fields with underscores to prevent collisions (thanks @Vincent550102 for the report and @dunglas for the patch)

:warning: These security patches may be breaking if your application relies on the buggy behaviors.

There are also several other various fixes and enhancements by many other contributors. Thank you everyone who participated!

What's Changed
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.11.3...v2.11.4

v2.11.3

This release improves several aspects of Caddy with minor features, bug fixes, and security patches. Thank you to everyone and their bots who contributed to help make this release the best one yet!

Security patches:

  • fastcgi: Carrying over a patch from FrankenPHP for a bug that could allow non-PHP files to be executed; collaborated on by @dunglas, @KC1zs4, and @chenjj.
  • vars: A more thorough fix for https://github.com/advisories/GHSA-m2w3-8f23-hxxf, collaborated by @everping and @vnxme.
  • admin: Array index normalization to prevent remote admin socket auth bypass, by @Amemoyoi and bot.
  • admin: More rigorous path prefix matching to prevent remote admin socket auth bypass, by @Amemoyoi and bot.

We've also merged a couple PRs that fix upstream security bugs in other projects like quic-go and CertMagic. Thank you to @marten-seemann for maintaining quic-go so diligently!

What's Changed
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.11.2...v2.11.3

v2.11.2

Caddy 2.11.2 contains numerous bug fixes and enhancements! I know that's a lame summary but it's really all over the place.

Highlights
  • Reverse proxy got a lot of love with certain edge cases related to PROXY protocol, health check port, and closing body on retries. Dynamic upstreams are now tracked which enables passive health checking.
  • Performance improvements for metrics.
  • New tls_resolvers global option to control DNS resolvers for all sites when using the ACME DNS challenge.
  • Log rolling now supports zstd compression; deprecated roll_gzip, which will be removed in the future. Use roll_compression instead.
  • Refined logging and some error messages.
  • Fixed a bug in rewrite handler that could cause some URIs to not be rewritten when URI path is an escaped form of target path. Thanks to @MaherAzzouzi for the report.
Security fixes

This release fixes two CVEs.

  • @NucleiAv reported a bug in the forward_auth directive that could permit identity injection and potential privilege escalation.
  • @sammiee5311 reported that vars_regexp double-expanded placeholders, allowing some unusual configs to reveal secrets.

In addition:

  • Built on Go 1.26.1 (also released today) which patches several CVEs.
  • Our documentation has been updated to note that file system case sensitivity may affect the behavior of the hide option of the file_server handler.

Thank you to everyone who contributed, and for our ongoing sponsorships that make this development possible!

Changelog
  • 88616e86e6e656738426bb86b4a42dcc20a59f77 api: Add all in-flight requests /reverse_proxy/upstreams (Fixes #7277) (#7517)
  • d935a6956c16902623b8e8f6d1aafec4f6124f46 autohttps: Ensure CertMagic config is recreated after autohttps runs (#7510)
  • 5d20adc7a97f70d6fe722099356cca2027908576 build(deps): bump github.com/smallstep/certificates (#7535)
  • 9371ee67c64d2d2c81f9530be0d9749ecdbd2b00 build(deps): bump the actions-deps group across 1 directory with 12 updates (#7536)
  • 9798f6964d58eb5703d1498804962faca2dae4ea caddyhttp: Avoid nil pointer dereference in proxyWrapper (#7521)
  • dc360828598440beb1dfdb21c0ba14e09bcd565b caddyhttp: Collect metrics once per route instead of per handler (#7492)
  • 174fa2ddb93f830370b05058d1ea51ad1512597d caddyhttp: Evaluate tls.client placeholders more accurately (fix #7530) (#7534)
  • eac02ee98f9f61d79ae774aa49aa102ddf2076ba caddyhttp: Limit empty Host check to HTTP/1.1
  • f283062d37c50627d53ca682ebae2ce219b35515 cmd: Custom binary names through CustomBinaryName and CustomLongDescription (#7513)
  • cd9e1660aa454e6536ad740c9d1aaecf3c3552ed cmd: Pass configFile, not configFlag, for reload command (#7532)
  • 7b34e3107eb6071fea3a3f94a5c913c32a55afd0 core: Check whether @id is unique (#7002)
  • 566e710991a6b752933178e2c6126181efc563aa fileserver: document hide case-sensitivity (F-CADDY-FILESERVER-HIDE-CASE-001) (#7548)
  • 2dd3852416e2b04bc90b98643673ec9e131c32e6 fix(caddyfile): Prevent parser to panic when no token were added by empty {block} (#7543)
  • 2dbcdefbbee68e7b4a31ac66361a0f4e3bcd2eea forward_auth: copy_headers does not strip client-supplied identity headers (Fixes GHSA-7r4p-vjf4-gxv4) (#7545)
  • ce203aa9e1ff2686777019f45c36c283debb7986 go.mod: Upgrade x/net
  • 76b198f586e4e2482a0278ba52c176cff70af8cf http: Sort auto-HTTPS redirect routes by host specificity (fixes #7390) (#7502)
  • 7ffb640a4da666203ab43396eaeb2b6b84bb983f httpcaddyfile: Fix missing TLS connection policies when auto_https is default (#7325) (#7507)
  • 45cf61b1276b2cf79ce0147df8fa48c96e8e5356 logging: Ensure slog error level logs don't print stack traces (#7512)
  • 987375297862d9cd0a3fa33cfb199c25e504ad1b logging: Support zstd roll compression (#7515)
  • 294dfff4435c31b7c8d20d26067365b0a0016610 logging: add DirMode options and propagate FileMode to rotations (#7335)
  • a6acb3902cb6453153db0738bd8210e093449ce1 proxyproto: Generated test coverage (#7540)
  • 11b56c6cfc25f8c814fa66cb02060548d12c4040 reverseproxy: Fix health_port being ignored in health checks (#7533)
  • db2986028fc573ae3add0a9a3381268dd7599267 reverseproxy: Track dynamic upstreams, enable passive healthchecking (#7539)
  • d7b21c610494e30e147de77a4783c18e5f206d99 reverseproxy: fix tls dialing w/ proxy protocol (#7508)
  • a5e7c6e232573b8a8df2946914a84a36070d4b9f reverseproxy: prevent body close on dial-error retries (#7547)
  • 2ab043b8903db4574b2fc7a625619018a072f082 reverseproxy: query escape request urls when proxy protocol is enabled (#7537)
  • fbfb8fc517728f85890cd46559c01bec9495bf17 rewrite: Force recomputing path when escaped path matches rewrite target
  • f145bce553a306ca6890fea782ca4e3b06787bbb tls: Add tls_resolvers global option for DNS challenge configuration (#7297)

v2.11.1

Our community is pleased to announce Caddy 2.11! Of note are new features, numerous bug fixes including several security patches, and various QoL ("quality-of-life") enhancements.

There are no code changes from v2.11.0 other than to a CI job. Due to a recent external change that broke our release process, the first release of 2.11 is v2.11.1.

Special Sponsor Shoutout

Extra big thanks to our major sponsors:

They, along with dozens of smaller sponsors, make this project and new releases possible, together with our maintainer team. Thank you all!

Notable changes
  • Encrypted ClientHello (ECH) keys are rotated automatically.
  • Time-rolling options for logs.
  • SIGUSR1 can now reload configuration if it was initially loaded from a file on the command line and did not get changed via the API.
  • Reverse proxy now automatically rewrites the Host header to the address of the upstream when the upstream is HTTPS (#7454)
  • log_append can now log request and response bodies, useful for debugging.
  • Our project now implements and requires Assistance Disclosures (for AI/LLMs) on issues, PRs, comments, replies, reviews, etc.
  • Many, many other minor improvements and bug fixes.

Thank you to everyone who was involved this release!

:warning: Security patches
  • fastcgi: CVE-2026-27590 by @dunglas and @AbdrrahimDahmani - Unicode case-folding length expansion causes incorrect split_path index (SCRIPT_NAME/PATH_INFO confusion) in FastCGI transport.
  • admin: CVE-2026-27589 by @1seal - Cross-origin requests attempted with no-cors mode could cause some API requests to succeed; such requests are now blocked. (In order for this to be practically exploitable, a web browser executing a malicious web page must be running locally to a production Caddy process.)
  • caddyhttp: CVE-2026-27588 by Asim Viladi Oglu Manizada - The Host matcher becomes case-sensitive for large host lists (>100), enabling host-based route/auth bypass.
  • caddyhttp: CVE-2026-27587 by Asim Viladi Oglu Manizada - The Path matcher skips case normalization for escape sequences, enabling path-based route/auth bypass.
  • caddytls: CVE-2026-27586 by @moscowchill - TLS client authentication silently fails open when CA certificate file is missing or malformed.
  • caddyhttp: CVE-2026-27585 by @parrot409 - Improper sanitization of glob characters in file matcher may lead to bypassing security protections.

:rotating_light: Notice for Caddy plugin maintainers: Dependabot will probably alert you to the security fixes in Caddy and urge you to upgrade it in your go.mod file. Please ONLY upgrade the Caddy dependency if there's a change to an exported API your plugin uses. (Then, turn Dependabot off.)

What's Changed
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.10.2...v2.11.1

v2.11.0-beta.2

Pre-release

Welcome to the second beta version of 2.11. We are closer to a final release. This includes some minor new features and enhancements, and a fix for the ZeroSSL API issuer.

Thank you to everyone who contributed!

Changelog
  • 8a87bb3ffb8706bbfcaada1d52008a8eb07ad790 build(deps): bump github.com/smallstep/certificates (#7381)
  • 7b031e1eb5bc0bae9a8394d93f20399932ebd4d3 build(deps): bump the all-updates group across 1 directory with 12 updates (#7421)
  • be5f49fbeb046fb123583e5887ddf576a312a8e4 caddyhttp: Fix logging on wildcard sites when SkipUnmappedHosts is true (#7372)
  • 6e0cbd0fa0d3022b41fc2c17b80f15402e685643 caddyhttp: create a placeholder for and log ech status (#7328)
  • 4037d0576094c5f9f570825601615b62cb8d85b1 caddyhttp: {http.request.body_base64} placeholder (#7367)
  • 7ebe72bbfe342688a325325ea79e46970d017eb7 caddypki: Add support for multiple intermediates in signing chain (#7057)
  • 3c9c67e804eb3db9a3ac6532ddd2434246058cd5 caddytls: ECH key rotation (#7356)
  • 374b7a637f2b6f8d0f2723ad2e7908a41023e8d5 caddytls: fix preferred chains options by appending values instead of replacing (#7387)
  • 6a4296b1a45d81f52bf8ab01d0bcaa4423fee3ff caddytls: panic when using tls.ca_pool.source.http -> tls.ca (#7393)
  • 9eabd443cb170ed846a70a84acf87002683ad29b cmd: Add --json flag to list-modules command (#7409)
  • b2d21f650a7ecd61d0a7ee85f3d423b89cddc371 go.mod: Upgrade CertMagic and ZeroSSL deps
  • 34fd2dfcff4a9533bd3b63da56edb782effe561d go.mod: update tscert package to latest (aea342f6) (#7397)
  • decc8a4d6fc476b21165400ddc3c02d94ee9f47f logging: log_append Early option, Supports {http.response.body} (#7368)
  • 409a0721354354a2d13e5c110be0f7f03363652b notify: implement windows service status and error notifications (#7389)
  • 1f1be3f4fe281643fd4ac8c1217d5ade7f82f6b9 tracing: Add span attributes to tracing module (#7269)
What's Changed
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.11.0-beta.1...v2.11.0-beta.2

v2.11.0-beta.1

Pre-release

Welcome to the beta version of 2.11. This is the first release made by our new, automated release process developed by @Mohammed90 that was carried out and approved entirely by our maintainer team (together with @francislavoie) without intervention from @mholt, the original Caddy author. This represents a significant step forward in project autonomy and growth, ensuring that the project's stability and longevity is not reliant upon a single person.

This first beta release was primarily to test our new workflow, so there's still a couple things left to do before the stable release.

Featured here are numerous, mostly minor, bug fixes and enhancements, mostly affecting edge cases or niche corners of the software; for example, proxying H2C or HTTP/3, obscure Caddyfile scenarios, and named socket activation.

Some notable changes:

  • SIGUSR1 can be used to reload configuration only if it was loaded from a file using the CLI, and not changed by the API since then.
  • We replaced "lumberjack", our logging library, with a fork "timberjack" that supports the oft-requested time-rolling ability.
  • Caddy can now bind listeners with named socket activation.

Before the final release, we expect ECH key rotation to be enabled as well as a few other patches/features

Thank you to our sponsors and contributors for all that you do!

Changelog
  • 5473eb95d8e94505b8c06955bd200f37179c54a2 encode: fix response corruption when handle_errors is used (#7235)
  • 13a4ec7597f8e9ebe105b0ee89102ba521f21173 basicauth: Implement argon2id (#7186)
  • 6d90c7707dac3026c1b28fba615b1962d2cd45e1 build(deps): bump github.com/slackhq/nebula from 1.9.5 to 1.9.7 (#7315)
  • eead249382ac14c29d82ec75f30df7638e879567 build(deps): bump golang.org/x/crypto from 0.43.0 to 0.45.0 (#7355)
  • 2d0f3f887bc1f70c52fc183ebcc6225f7f91c041 build(deps): bump the actions-deps group with 5 updates (#7237)
  • afbdcec08bbd7471b9b5e5ed209881dfcc51bd6c build(deps): bump the actions-deps group with 8 updates (#7284)
  • cd1c203777e89a64c8426c049727c58fbebc1276 build(deps): bump the all-updates group across 1 directory with 2 updates (#7307)
  • 39357d3e5cb6124e8af651460cc8ab6975c637b8 build(deps): bump the all-updates group with 17 updates (#7236)
  • 786d5378771d068440b7ddd8c310851bb7b9afe0 build(deps): bump the all-updates group with 3 updates (#7376)
  • 07d2aaf22ef8225575b9557640806bc895067905 build(deps): bump the all-updates group with 4 updates (#7333)
  • 0ba8786b35eaec5ec53f8562bec9587e6b1e6a8b caddyfile: Allow block to do nothing if nothing passed to import (#7206)
  • 92c8bc73228aad9eb0b396fdb687c024124d8dbd caddyfile: fix nested quotes formatted incorrectly by fmt (#7045)
  • 6d73d85c1fd3d20acaaadc0fb69e3f562d92f685 caddyfile: prevent adding trailing space on line before env variable (#7215)
  • d7185fd002a2c57d20a98d3e94442da7b259b3ad caddyhttp: Add trusted_proxies_unix for trusting unix socket X-Forwarded-* headers (#7265)
  • de6b78009b840eb395c33b8d65c5d32746df38b6 caddyhttp: Add server options keepalive_idle and keepalive_count (#7298)
  • e0a8f9541d155b7385b78d2b8bbe2fad53bb6295 caddyhttp: Normalize (lowercase) {label.N} placeholders
  • 5e2953670ed7eecbc34146b5d12cca7dd85ac580 caddyhttp: add replacer placeholders for escaped values (#7181)
  • 8285eba8426e3c75ed81d6a8c5cd6ec685430d47 caddyhttp: allow customizing the Server header (#7338)
  • bc0e1841305b2cc82aeaf9953e527d9819a88c83 caddyhttp: omit unnecessary reassignment (#7276)
  • 3553cfb6adb2954a53d559c1841c8072b9921e61 caddyhttp: remove redundant middleware next copy (#7217)
  • 1ce2a13ad10eab5693b425056c571621f5d860e9 caddyhttp: wrap accepted connection to suppress tls.ConnectionState (#7247)
  • d9cc24f3df663e1bab58dc08ac12bf818c9f6852 caddypki: Disable internal auto-CA when auto_https is disabled (fix #7211) (#7238)
  • 1e82f9652ec561cc0c84bec501976045aa01a310 caddypki: check intermediate lifetime to actual root cert lifetime (#7272)
  • 38848f7f2525777edd0241ad3118f070e045d771 caddytls: Allow disabling distributed solving (except http-01)
  • ddec1838b39a1b61432db4e78f2e752f27c3c769 caddytls: correct documentation of LeafFolderLoader (#7327)
  • f5c3094050566d8d4fcf9f3ecf7d26f9c3241c65 cmd: prevent commas in header values from being split (#7268)
  • 65e0ddc22137bbbaa68c842ae0b98d0548504545 core: Reloading with SIGUSR1 if config never changed via admin (#7258)
  • b3f2db233b5a71df6680b43d025bdb62ee2a999c core: custom slog handlers for modules (log contextual data) (#7346)
  • b2ab419922e0dabc2956611531f73a6169ecc46f core: use reflect.TypeFor to check for encoding/json.RawMessage (#7274)
  • 806fef85bedfc3fe178560afe6212c8ae90d3ebe encode: add graphql-response header to list (#7214)
  • 2cb426776c091febccc6b9a6669f1c5a745648a4 encode: modernize, replace HasSuffix+TrimSuffix with CutSuffix (#7357)
  • b462615439bf354dd1cb6780fb564b6a6c4a352c fileserver: set Content-Length for precompressed files (#7251)
  • 0c8798fce36b0915ff39288bff7eddfad2a1673f go.mod: update quic-go to v0.54.1 (#7273)
  • 3c003deec67ed1ca0127f4b303c64760a9a7b19d httpcaddyfile: Add missing DNS challenge check for acme_dns (#7270)
  • 2f1d270968e050105e3f6814b1ef7e7660ed41ba httpcaddyfile: Map default_bind to BindHost in globalACMEDefaults (#7278)
  • a7885aabec375db38ac6c221c7c709dc83122535 intercept: use already buffered response if possible when intercepting (#7028)
  • 156ce99d3a46be8cefe8502b2c30b757e4deb79f listeners: Add support for named socket activation (#7243)
  • 39ace450deb23a8ebb4f41ff4d8cfe2800d68118 logging: Adjustments to BufferedLog to keep logs in the correct order (#7257)
  • 012b4b3d40dae32502503c9d6bc6333acb135cb3 logging: Buffer the logs before config is loaded (#7245)
  • 10ac7da037828c5179ad7d04309fc8912f2fe0d5 logging: Switch from lumberjack to timberjack, add time-rolling options (#7244)
  • f5f25d845a814a600102614cc8836af5ebe1487b logging: fix multiple regexp filters on same field (fixes #7049) (#7061)
  • 595aab8bc0d98c510c044a2a6b8e7053aaf4e8fb metrics: resolve per-host inifinite cardinality (#7306)
  • 57587ed18e3908931b4f7bfd73078c47082fb742 refactor: use reflect.TypeFor (#7313)
  • 2ec28bca43e5269511f8d9c1656244dd84acdad9 reverse_proxy: use http1 for outbound tls requests with placeholder that are likely websockets (#7296)
  • a6da1acdc86199a7f99fa2347d5f91cd59ff90d8 reverse_proxy: use interfaces to modify the behaviors of the transports (#7353)
  • 67a9e0657e60df8c78510065e8977d86ee17d01c reverseproxy: Fix retries for requests with bodies (#7360)
  • 7fb39ec1e56751c82950fa8a35a189ea39dfa005 reverseproxy: Use http1.1 upgrade for websocket for extended connect of http2 and http3 (#7305)
  • 8aca108d2c9d9e9ff3a39ff00684ea58df1338f6 reverseproxy: do not disable keepalive if proxy protocol is used (#7300)
  • abe0acabb61b0151f58c7b750d3963dbbffe7270 reverseproxy: set default values for keepalive if only some of them are set (#7318)
  • 1e21b660c42485cb47287b595900446093d3df2b reverseproxy: use http.Protocols to handle h2c requests (#6990)
  • b54e870b26a23a98d81967c80d9e875f3a9e3c1d tracing: switch to autoexport for OpenTelemetry span exporter (#7317)
What's Changed
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.10.2...v2.11.0-beta.1

v2.10.2

This is a hotfix release to fix a couple critical issues from v2.10.1

What's Changed
Changelog
  • 551f793700fe1550845c824470b623fd1aa03d36 caddyfile: Fix importing nested tokens for {block} (#7189)
  • 16fe83c7afe2152b0bb53ae35078a28f87e6dcf2 http: Make logger first, before TLS provisioning (#7198)
  • 4564261d8350f8010b7e001e646e260e9bba5746 httpcaddyfile: Fix acme_dns regression (#7199)
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.10.1...v2.10.2

v2.10.1

This is probably our biggest patch release ever -- not that lots of things were broken, but there's lots of refinement happening thanks to broader adoption and contributions from many more people. Just look at the New Contributors below!

Anyway, this release does contain some bug fixes and dependency upgrades which we hope will serve you well. Let us know if there's any issues! And thank you to all who contributed, especially our reliable maintainer team!

This version of Caddy requires Go v1.25.0 or newer.

What's Changed
Changelog
  • 44d078b6705c7abcabb2a60f501568ff7f5a57a1 acme_server: fix policy parsing in caddyfile (#7006)
  • 320c57291dbe06e00e0759bdb5cbbf0d622e5968 admin: Make sure that any admin routers are provisioned when local/re… (#6997)
  • 49dac61b078a704b3e98566134c108d6def19450 bcrypt: add cost parameter to hash-password (#7149)
  • 4bfc3b95b5f88a1042a5103d8ad3fac3f42bf129 bcrypt: wrong cost flag name (#7168)
  • 4b01d77b81a9ebda046637026cf57671a3cc5859 build(deps): bump github.com/cloudflare/circl from 1.6.0 to 1.6.1 (#7058)
  • 45c9341deb9818638ab389b98e7b4c74dc9f6afc build(deps): bump golangci/golangci-lint-action from 6 to 8 (#7044)
  • 5bc2afbbb6ee5bc1537b521fd507506fd86ae43f build(deps): bump the actions-deps group with 6 updates (#7142)
  • 007f4066f6abf55f42195155117c53b230490a73 build(deps): bump the all-updates group across 1 directory with 17 updates (#7155)
  • 8524386737e7dcaf6ab2378e5bc9456f82b91cd1 caddyhttp: Compare paths w/o wildcard if prefixes differ (#7015)
  • 7590c9ca1ba6096408574a7dd3b9dc42d12cb948 caddyhttp: Free up quic listener when stopping (#7177)
  • b15ed9b0844dd7b73977f4c6dacfb3348579ce4a caddyhttp: refactor to use reflect.TypeFor (#7187)
  • 14a63a26b9a673857fc37cba37aedc35a10ce634 caddyhttp: use the new http.Protocols to handle h1, h2 and h2c requests (#6961)
  • 731e6c24821630f7ac117ff74188e79a06a75d1e caddytls: Improve ECH error logging (close #7152)
  • 105eee671c384459de666889be953857a7175afa caddytls: Set local_ip, not remote_ip (#6952)
  • b898873b90b5cb804400888ec2f2994f6a2dd270 caddytls: fix regression in external certificate manager support (#7179)
  • 1481c0411aa3ce3a53c206e18ee9ce4223cc156d caddytls: wire up client_auth leaf verifier Caddyfile (#6772)
  • 19ff47a63b9ff2ae424790b02548d9ba4afc56ba cmd: Allow caddy adapt to read from stdin (#7163)
  • e633d013f64d057f462786ccf4a430cd27817d4d cmd: fix Commands function not returning all registered commands (#7059)
  • 7099892958fbee17f5e087c768f4db1940303fa8 core: Check for nil event origin (#7047)
  • 3d0b4fac5a583d615fe411a4af9a24a7bcc3bee3 core: Clean up new config if it failed to run (#7068)
  • 051e73aefca4cc3d930e8b637d848deb5e100126 core: Replace admin server later in provisionContext (#7004)
  • fe41ff3c5bbee0aaa44110c110fd6b4fbf052048 core: Save app provisioning errors with context (#7070)
  • e4447c4ba783482c35b096cfbe0e0ffa0403b450 core: Use KeepAliveConfig to pass keepalive_interval to listener's accepted sockets (#7151)
  • b9710c6af4f764b463a8e0c080783f2b7fb15ce0 fileserver: Add a few doc lines about Etag file content (#7173)
  • 3b4d966fba069e9895980dbbf05f84bf818968ba fileserver: Add sort buttons in grid mode (#7089)
  • 54d03ced48a8ed2264ae9248c81f00a1c2648d82 fileserver: Add support for .avif image format (#6988)
  • 790f3e0885cae4f6362f35f8ed4f725824d46089 fileserver: denote license for embedded JavaScript for LibreJS (#7127)
  • 94147caf31f7e56a919432accc2779a22b2ed1a0 fileserver: map invalid path errors to fs.ErrInvalid, and return 400 for any invalid path errors. (close #7008) (#7017)
  • 67debd0e11c3c880bb6fc7a92325989576b0a7fa fileserver: set Range header for precompressed static files to force Content Length header to appear (#7042)
  • 89ed5f44de61fcb0c3b7ce93bfefbb8e775d1964 fix: Remove nil arg from zapslog.NewHandler call (#6984)
  • 3723e895854a1f9e528ec278acb0ed8ef1c63f81 go.mod: Upgrade CertMagic to v0.24.0
  • 3bd413546bf8f7b5e19fcb2104a21600c55cc146 go.mod: Upgrade dependencies
  • a6d488a15beb01369384e74d0e0159da11272bc3 go.mod: update quic-go to v0.51.0 (#6972)
  • 11c6daecd7663bd625ec823f585a1c502468b1e7 go.mod: update quic-go to v0.53.0 (#7094)
  • bbf1dfcea283c4b002f2e4c970d2def38fa2046f headers: Support placeholders in replacement search patterns (#7117)
  • f11c780fdc2e4e5298a64ef88d110dd392060a36 http: clean up listeners if some of the listeners fail to bind (#7176)
  • fdf610850b5e5dcb518eb2ad475817d6990b8a8d http: disable keepalive when KeepAliveInterval is negative (#7158)
  • 5b727bde2992e7cb9987208453db42ae6e1c6e1e httpcaddyfile: Allow naked acme_dns if dns is set (fix #7091)
  • 0badb071efc38bb9cc055076f0a48d1725fe8cc8 httpcaddyfile: Fix generated config related to ACME global options
  • 092913a7a568a5eb4b28c06e12c1274bd5eb1140 httpcaddyfile: Prevent error handler from overriding sub-handler matchers (#6999)
  • 77dd12cc785990c5c5da947b4e883029ab8bd552 httpcaddyfile: Validates TLS DNS challenge options (#7099)
  • 0f209f62eb1f33e67070ada7fa6f4a7899b8e99d httpcaddyfile: reject blocks in log_skip directive (#7056)
  • 716d72e47538cc4f7bab43b1d973e0f8aa0a9fba intercept: implement Unwrap for interceptedResponseHandler (#7016)
  • 9f7148392adb72a6121bf99070efaa1a90ffe901 log: default logger should respect {in,ex}clude (#6995)
  • 33c88bd2bb543a726274cdf52899edb0639cf5f6 refactor: replace HasPrefix+TrimPrefix with CutPrefix (#7095)
  • ab3b2d64ba9bf7dadd4440a84894ebab0ee6d5ea refactor: use slices.Equal to simplify code (#7141)
  • 1c596e3c5a1cd0b52febb1506ffe471918bd1128 reverse_proxy: use the new KeepAliveConfig to set probe interval (#7157)
  • aa3d20be3ee451af9465470a28937690104e9422 reverseproxy: Use DialTLSContext if ServerName has placeholder (#6955)
  • 737936c06be001a40c2d743d17d1e3df148408f0 reverseproxy: reference correct field name in LoadModule (#6978)
  • 1209b5c5669fc5d0a708931f138bfa7a5d4c5ebc reverseproxy: validate versions in http transport (#7112)
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.10.0...v2.10.1

v2.10.0

Caddy 2.10 is here! Aside from bug fixes, this release features:

  • Encrypted ClientHello (ECH): This new technology encrypts the last plaintext portion of a TLS connection: the ClientHello, which includes the domain name being connected to. 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; we highly recommend reading the ECH documentation on our website.
  • 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 the dns parameter in the tls app configuration.
  • Wildcards used by default: Previously, Caddy would obtain individual certificates for every domain in your config literally; now wildcards, if present, will be utilized for subdomains, rather than obtaining individual certificates. This change was motivated by the novel possibility for subdomain privacy afforded by ECH. It can be overridden with tls force_automate in the Caddyfile. The experimental auto_https prefer_wildcard option has been removed.
  • libdns 1.0 APIs: Many of you use DNS provider modules to solve ACME DNS challenges or to enable dynamic DNS. They implement interfaces defined by libdns to get, set, append, and delete DNS records. After 5 years of production experience, including lessons learned with ECH, libdns APIs have been updated and 1.0 beta has been tagged. DNS provider packages will need to update their code to be compatible, which will help ensure stability and well-defined semantics for the future. Several packages have already updated or are in the process of updating (cloudflare, rfc2136, and desec to name a few).
  • Global 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! :tada: :partying_face: :champagne:

:warning: While have traditionally supported the last 2 minor Go versions to accommodate some distribution / package manager policies, we now only support the latest minor Go version. The privacy and security benefits added in new Go versions (such as post-quantum cryptography) are worth making available to everyone as soon as possible, rather than holding back the entire user base or maintaining multiple code compilation configurations.

Encrypted ClientHello (ECH) details

(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).

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:
  • 96c5c554c1241430ac9ddea6f4b68948adcc961b admin: fix index validation for PUT requests (#6824)
  • 3644ee31cae8e20493d7ccd0c55b0a9c21f20693 build(deps): bump github.com/cloudflare/circl from 1.3.3 to 1.3.7 (#6876)
  • eacd7720e99f51b6d2dd340849897c0ff812b8c8 build(deps): bump github.com/go-jose/go-jose/v3 from 3.0.3 to 3.0.4 (#6871)
  • 9996d6a70ba76a94dfc90548f25fbac0ce9da497 build(deps): bump github.com/golang/glog from 1.2.2 to 1.2.4 (#6814)
  • 11151586165946453275b66ef33794d41a5e047b caddyhttp: ResponseRecorder sets stream regardless of 1xx
  • 8861eae22350d9e8f94653db951faf85a50a82da caddytest: Support configuration defaults override (#6850)
  • d7764dfdbbee04d2f63aa1b05150737dfddc0bcf caddytls: Encrypted ClientHello (ECH) (#6862)
  • a807fe065959baa8ee2ad95156183c0850c2b584 caddytls: Enhance ECH documentation
  • bc3d497739444a5ce550696b7b0da36e6e3bc777 caddytls: Fix broken refactor
  • 7b8f3505e33139de0d542566478e98b361bb84bf caddytls: Fix sni_regexp matcher to obtain layer4 contexts (#6804)
  • 2c4295ee48f494bc8dda5fa09b37612d520c8b3b caddytls: Initial support for ACME profiles
  • d7872c3bfa673ce9584d00f01a725b93fa7bedf1 caddytls: Refactor sni matcher (#6812)
  • 172136a0a0f6aa47be4eab3727fa2482d7af6617 caddytls: Support post-quantum key exchange mechanism X25519MLKEM768
  • 066d770409917b409d0bdc14cb5ba33d3e4cb33e cmd: automatically set GOMEMLIMIT (#6809)
  • 1f35a8a4029a338e89998acafa95e1e931a46a27 fastcgi: improve parsePHPFastCGI docs (#6779)
  • 22563a70eb7b590fcb698680a3ec6d76c0968748 file_server: use the UTC timezone for modified time (#6830)
  • cfc3af67492eba22686fd13a2b2201c66cd737f3 fix: update broken link to Ardan Labs (#6800)
  • 99073eaa33af62bff51c31305e3437c57d936284 go.mod: Upgrade CertMagic to v0.21.7
  • 1641e76fd742408c85363e4826451ba9ef22bc99 go.mod: Upgrade dependencies
  • 0d7c63920daecec510202c42816c883fd2dbe047 go.mod: remove glog dependency (#6838)
  • 932dac157a3c4693b80576477498bb86208b9b30 logging: Always set fields func; fix #6829
  • 9e0e5a4b4c2babda81c58f28fe61adfa91d04524 logging: Fix crash if logging error is not HandlerError (#6777)
  • 904a0fa368b7eacac3c7156ce4a1f6ced8f61f34 reverse_proxy: re-add healthy upstreams metric (#6806)
  • e7da3b267bcec986aaca960dd22ef834d3b9d4a6 reverseproxy: Via header (#6275)
  • 9283770f68f570f47ca20aa9c6f9de8cc50063ba reverseproxy: ignore duplicate collector registration error (#6820)
Beta 2:
  • f4432a306ac59feee1fc45c8efefad3619e37629 caddyfile: add error handling for unrecognized subdirective/options in various modules (#6884)
  • 84364ffcd06e35a93c9bb08ed80617bde72d4f74 caddypki: Remove lifetime check at Caddyfile parse (fix #6878)
  • adbe7f87e6bda96a1dddd94ecedefe3219a5304d caddytls: Only make DNS solver if not already set (fix #6880)
  • d57ab215a2f198a465ea33abe4588bb5696e7abd caddytls: Pointer receiver (fix #6885)
  • 4ebcfed9c942c59f473f12f8108e1d0fa92e0855 caddytls: Reorder provisioning steps (fix #6877)
  • a686f7c346fe011ad153a3bd4ac3e31e6758bcce cmd: Only set memory/CPU limits on run (fix #6879)
  • 19876208c79a476a46beec2430e554d4161ab426 cmd: Promote undo maxProcs func to caller
  • 220cd1c2bcecc07bcf6a0141069538c1b1109907 reverseproxy: more comments about buffering and add new tests (#6778)
Beta 3:
  • b3e692ed09f8ba15b741621c4b16d8bfee38f8a1 caddyfile: Fix formatting for backquote wrapped braces (#6903)
  • 55c89ccf2a39dcfd7286fcaed54787821ff9a1aa caddytls: Convert AP subjects to punycode
  • 1f8dab572ca9681464fdadc65bfb5f250fc496c3 caddytls: Don't publish ECH configs if other records don't exist
  • 782a3c7ac60c82311fe9fb8889dd843dfe26c0bc caddytls: Don't publish HTTPS record for CNAME'd domain (fix #6922)
  • 49f9af9a4ab2a28fa5c445630017f5284a5afa48 caddytls: Fix TrustedCACerts backwards compatibility (#6889)
  • e276994174983dbb190d4bb9acaab157ef14373b caddytls: Initialize permission module earlier (fix #6901)
  • 39262f86632401ae4915600b042ef5a28141d3d5 caddytls: Minor fixes for ECH
  • 173573035c7484bb4aad4498a90bf5a1cf1bb5be core: add modular network_proxy support (#6399)
  • 86c620fb4e7bfad5888832c491147af53fd5390a go.mod: Minor dependency upgrades
  • af2d33afbb52389cda139a6a0fd8a9d65f558676 headers: Allow nil HeaderOps (fix #6893)
  • dccf3d8982d1b428e840d43f71fa5c3becf6ea8f requestbody: Add set option to replace request body (#5795)
  • 2ac09fdb2046957597e17096adf6335a6d589a2f requestbody: Fix ContentLength calculation after body replacement (#6896)
v2.10.0:
  • f297bc0a04dcab6c2585b47f3672d045c4f6b54b admin: Remove host checking for UDS (close #6832)
  • 0b2802faa47faa378181a3de5b0d1dcc769a715d build(deps): bump golang.org/x/net from 0.37.0 to 0.38.0 (#6960)
  • 5be77d07ab730e6035ec7a47fb0fe161785af35c caddyauth: Set authentication provider error in placeholder (#6932)
  • b06a9496d130cb06466156d53138a9691342e5a2 caddyhttp: Document side effect of HTTP/3 early data (close #6936)
  • 35c8c2d92d26208642cea0d1549c77a00124e154 caddytls: Add remote_ip to HTTP cert manager (close #6952)
  • fb22a26b1a08a2fa3b2526d1852467904ee140f6 caddytls: Allow missing ECH meta file
  • 1bfa111552eff8b30bc1a5f76516426f29c66a88 caddytls: Prefer managed wildcard certs over individual subdomain certs (#6959)
  • ea77a9ab67d8c04f513adaf0a1c648c738e25922 caddytls: Temporarily treat "" and "@" as equivalent for DNS publication
  • 5a6b2f8d1d4633622b551357f3cc9d27ec669d02 events: Refactor; move Event into core, so core can emit events (#6930)
  • 137711ae3e2d9aa48d7c48dba5ca176af628f073 go.mod: Upgrade acmez and certmagic
  • 9becf61a9f5bafb88a15823ce80c1325d3a30a4f go.mod: Upgrade to libdns 1.0 beta APIs (requires upgraded DNS providers)
  • 6c38ae7381b3338b173c59706673d11783091dee reverseproxy: Add valid Upstream to DialInfo in active health checks (#6949)
What's Changed
New Contributors

Full Changelog: https://github.com/caddyserver/caddy/compare/v2.9.1...v2.10.0

Discussion