Releases: caddyserver/caddy
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
We're pleased to present the next previews of Caddy 2.9! While in beta, new features and changes may be unstable, so please test in suitable environments that may expose issues so we can fix them before the stable release.
While there are some features in this release (such as socket-activation-listeners), we've focused mainly 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)
We hope you will enjoy the 2.9 beta releases. Please try them out and report bugs! There is still more to come before the stable 2.9.0 release!
Thanks to all contributors, bug reporters, and helpers.
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 support for TLS connection and certificate selection policies by @vnxme in #6462
- chore: update golangci config by @mohammed90 in #6479
- encode: flush already compressed data to the stream by @WeidiDeng in #6471
- proxyprotocol: Update WrapListener to use ConnPolicyFunc for PROXY protocol by @pi-prakhar in #6485
- fileserver: add
sort
options by @lollipopkit in #6468 - go.mod: update quic-go package by @WeidiDeng in #6498
- Runtime placeholders for selected TLS and HTTP matchers by @vnxme in #6480
- replacer:
{file.*}
global placeholder strips trailing newline by @steffenbusch in #6411 - go.mod: update update golang/x/net by @WeidiDeng in #6500
- reverse_proxy: apply keep-alive setting for h2c requests by @WeidiDeng in #6343
- Fix a regression in #6480: the context may have no replacer by @vnxme in #6510
- caddyhttp: Export PrivateRangesCIDR() for plugins after #6480 by @vnxme in #6514
- ignore exec.ErrDot when starting caddy in background by @WeidiDeng in #6512
- ci: don't exit early on error in remote CI machine by @mohammed90 in #6519
- reverseproxy: Active health checks request body option by @jbro in #6520
- reverseproxy: Change logs for write errors to warn level by @jum in #6532
- cmd: Use a factory to create the caddy root command by @elee1766 in #6533
- chore: Fix a typo by @sunnyagain in #6534
- error: run
error
(msg) through replacer by @mohammed90 in #6536 - reverseproxy: allow user to define source address by @mohammed90 in #6504
- chore: build and test with Go 1.23 by @dunglas in #6526
- tls: use Go default kex for the moment that include PQC by @bwesterb in #6542
- ci: prepare syso files for windows embedding in release by @WeidiDeng in #6406
- Performance: Prevents the zap logger from serializing the request in rewrite.go. by @AlliBalliBaba in #6541
- fileserver: move
sort
tobrowse
by @lollipopkit in #6502 - reverse_proxy: add placeholder http.reverse_proxy.retries by @steffenbusch in #6553
- fix(#6551): Unexpected behaviour if caddyhttp.Route is provisioned twice by @jbro in #6558
- caddytls: Add sni_regexp matcher by @vnxme in #6569
- rewrite: Avoid panic on bad arg count for
uri
by @mister-turtle in #6571 - perf: use zap's Check() to prevent useless allocs by @dunglas in #6560
- ci: update the linter action version by @mohammed90 in #6575
- update quic-go to v0.47.0 by @marten-seemann in #6582
- quic: enable qlog, controlled by QLOGDIR env by @marten-seemann in #6581
- caddytls: Give a better error message when given encrypted private keys by @francislavoie in #6591
- chore: Use slices package where possible by @francislavoie in #6585
- caddyhttp: Optimize logs using zap's WithLazy() by @AlliBalliBaba in #6590
- doc: remove docs of deprecated directives by @mohammed90 in #6566
- Implement issue #6296 passing FDs / socket activation by @MayCXC in #6573
- caddyhttp: Fix listener wrapper regression from #6573 by @MayCXC in #6599
- chore: Adjust incorrect
reverse_proxy
Caddyfile comment by @francislavoie in #6598 - http: ReponseWriter prefer ReadFrom if available by @WeidiDeng in #6565
- caddytls: Support new tls.context module by @mholt in #6369
- Better errors when reloading by @mholt in #6601
- caddyhttp: Escaping placeholders in CEL, add
vars
andvars_regexp
by @francislavoie in #6594 - autohttps: Implement
auto_https prefer_wildcard
option by @francislavoie in #6146 - metrics: scope metrics to active config, add optional per-host metrics by @mohammed90 in #6531
- ci: install xcaddy to fix release flow by @mohammed90 in #6602
- caddytls: Drop
rate_limit
andburst
, has been deprecated by @francislavoie in #6611 - tests: Fix adapt test warning by @mohammed90 in #6619
- docs: expand...
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
v2.8.1
v2.8.0
Caddy 2.8 is here! With hundreds of improvements, Caddy is more scalable and capable than ever before. Featuring ACME Renewal Information (ARI) support, HTTP/3 to proxy backends, and so much more than we can list in a sentence, we are pleased to bring you one of the biggest Caddy updates yet. Documentation on our website will be updated in the coming days.
We've implemented a ton of improvements, fixes, and awesome new features based on your feedback. While some of them aren't particularly visible changes, they allow Caddy to scale better and be more reliable in demanding deployments. Many of the changes are quality-of-life improvements we hope you'll appreciate. Then there's improvements to ACMEz, CertMagic, and other dependencies which make Caddy better that may not show up in this list.
There was a lot of code that had been documented as deprecated in place for a long time, so this version introduces a few more breaking changes than usual; please review the notes below.
Thank you to our sponsors and everyone in the community who contributed -- over 40 of you made your first contribution for this release. We couldn't have done it without your help. In particular, we'd like to recognize sponsors Stripe, Framer, and ZeroSSL for their positive influence which have greatly enhanced the project. Caddy 2.8 is already being used in our sponsors' large-scale, multi-region production deployments.
Want to join those ranks? Sponsor the Caddy project and benefit from development priority, dedicated private support, and much more.
As with any server upgrades, please be sure to test and validate your configurations in a staging or test environment before deploying to production. Thank you and have a great day!
- ZeroSSL (#6229) (this is one overall change, but requires some explanation):
- Up to now, Caddy used both Let's Encrypt and ZeroSSL by default to get certificates without any configuration. In 2.8, this is changing slightly. Due to upcoming changes to ZeroSSL accounting policies, ZeroSSL now requires your email address to be able to access their free ACME endpoint.
- As such, Caddy will only implicitly add the ZeroSSL issuer to your config if you provide an email address in your Caddyfile using the
email
global option. (We have already recommended this for years.) If you already do this, you don't have to make any changes and you'll still get Let's Encrypt and ZeroSSL automatically as defaults. - If you use JSON to configure certificate automation policies, you will need to ensure you use the
acme
issuer with youremail
filled out, and theca
field set to ZeroSSL's ACME server URL. If you want redundancy with Let's Encrypt, be sure to specify anotheracme
issuer as well (defaults OK, but we recommend setting an email there too). - The
zerossl
issuer module is no longer ACME-capable and is now exclusively for the ZeroSSL API. An API key from your ZeroSSL account is required. (The ZeroSSL ACME server can still be used with theacme
module pointed to ZeroSSL's ACME server. You can provide your account email and/or EAB as well.) If you were using the ZeroSSL issuer with an API key, it will now start using ZeroSSL's API, which was probably the expected behavior anyways. The API has several advantages over the ACME endpoint, but may require payment:- Faster response times
- IP certificates
- Management tools in your ZeroSSL account dashboard
- Technical support
- To clarify, Let's Encrypt is still a default issuer even if you don't provide an email address (but we have always strongly recommended to do so).
- You can still use ZeroSSL's ACME endpoint with your own External Account Binding (EAB) credentials.
- See notes in #6229 for some examples and further explanations.
- Removed support for the
lego_deprecated
DNS provider module. It has been deprecated for 4 years. Usecaddy-dns
modules instead; there are over 50 to choose from already. They are more flexible, compile much leaner, and are easier to implement and support. If yours is not supported it can be easily implemented. Sponsors at or above the Business tier can request to have their provider implemented for free. - On-demand TLS: The
ask
option in the JSON has been deprecated in favor of a permission module (Caddyfile unchanged) (#6055), and Caddyfile support forpermission
modules is added (6a02999) - Admin API:
Etag
(used for concurrency control) is now a header, not a trailer. This is less efficient, but still virtually no clients properly implement trailer support. - For consistency, the
basicauth
Caddyfile directive has been renamed tobasic_auth
(#6092), andskip_log
has been renamed tolog_skip
. The old names will continue to work for now, with a deprecation warning in the logs. (#6066). - The
basic_auth
handler no longer supportsscrypt
(deprecated for nearly two years) (#6091) - The
forwarded
option has been deprecated for a long time and has now been removed from theremote_ip
matcher. Use theclient_ip
matcher instead. (#6085) - Reverse proxy: The
buffer_requests
,buffer_responses
, andmax_buffer_size
settings have been removed after being deprecated for 14 months. Userequest_buffers
andresponse_buffers
instead if you need buffering. - Go API: If you called
caddy.Context.AppIfConfigured()
, it now returns an error, as part of a bug fix. (#6292)
Notable changes:
- acme_server: Configurable allow/deny policies (#5796)
- acme_server: Specify allowed challenge types (#5794)
- caddyfile: Plugin authors can now specify a default ordering for directives, making manual ordering by users less necessary (#5865)
- cmd: The
--adapter
flag is not needed for config files ending with.caddyfile
(#5919) - encode: More media types are now compressed by default (#6081)
- encode: Modify ETag when encoding to comply with RFC 9110 section 8.8.3 (#5849)
- encode: Configurable compression level for
zstd
(#6140) - handle_errors: Handling can now be filtered by response status code more easily (#5965)
- http: New
fs
directive can declare a file system plugin to use (#5057) - http: Sensitive headers in the logs are now replaced with
["REDACTED"]
instead of empty array. (#5669) - http: Several improvements to size logging, websockets, flushing, 1xx statuses, and QUIC. (#6173, #6175, #6202, #6150, #6164, #6168)
- http: Can now write access logs for a hostname to more than one logger (#6088)
- http: The
log_append
handler can add fields to the access logs (#6066) - http: Add
uuid
field to access logs when the{http.request.uuid}
placeholder is used (#5859) - http: Changed PROXY protocol libraries add TLV support (#5915)
- http: A new tracing mode writes each individual middleware handler to logs (#6313)
- http: Access logs use a different message ("unhandled") when an HTTP request is a no-op (#5182)
- file_server: The browse feature can now return a plaintext response (useful for terminals) (#6093)
- file_server: File listings can dereference symlinks if enabled (#5973)
- file_server: Directory listings now include total file size (#6003)
- file_server: Can use precomputed ETags from sidecar files (#6222)
- replacer: A new
{file.*}
global placeholder is available, where*
is a path to a file on disk which contains a value (generally used for secrets) (#5463) - reverse_proxy: HTTP/3 supported to backends (experimental) (#6312)
- reverse_proxy: Active health checks can now be configured with consecutive passes/fails to change status (#6154)
- reverse_proxy: A forward proxy can now be specified in config other than a single env var (#6114)
- reverse_proxy: Configurable trusted root CAs is now modular (#6065)
- reverse_proxy: SRV upstreams now support failovers/grace period with cache (#5832)
- reverse_proxy: TLS curves can now be configured (potential preparation for post-quantum) (#5851)
- root, rewrite: A
*
matcher token is no longer required in the Caddyfile (#5844) - tls: Client authentication validation methods are now modular/pluggable (#6050)
- tls: Trusted CA providers are now modular (#5784)
- tls: New
local_ip
connection matcher (#6074) - tls: Improvements and fixes when certificate managers are configured (#6229)
- tls: Refactor the On-Demand TLS
ask
endpoint into apermission
module, making it pluggable (#6055) - tls: Storage cleaning is now synced across instances that share the storage (#5940)
- tls: Supports ACME Renewal Information (ARI) draft spec, together with cert lifetime and OCSP/revocation status, to trigger certificate renewals
- uri: Can now perform structured query rewrites with
uri query
(#6120, #6165)
Changelog
Full Changelog: v2.7.6...v2.8.0
- ac0ad4d Upgrade acmeserver to github.com/go-chi/chi/v5 (#5913)
- 931656b acmeserver: add policy field to define allow/deny rules (#5796)
- e1aa862 acmeserver: support specifying the allowed challenge types (#5794)
- e6f46c8 acmeserver: Add
sign_with_root
for Caddyfile (#6345) - 4a0492f admin: Make
Etag
a header, not a trailer (#6208) - 1217449 admin: Use xxhash for etag (#6207)
- 7e2510e build(deps): bump ...
v2.8.0-rc.1
This release is obsolete. Please see the next release for the notes.
v2.8.0-beta.2
This release is obsolete. Please see the next release for the notes.
v2.8.0 beta 1
This release is obsolete. Please see the next release for the notes.