Caddy 2.5 introduces new features you'll love as well as a huge number of bug fixes and enhancements. Thank you to everyone who contributed.
⚠️ This is a release candidate version. We think it's stable enough to use in production, but we want to be extra sure, so please try it out! It needs to be used and tested for regressions. Let us know if there are any issues.
Documentation on the website has mostly been updated (JSON docs will be last). Feel free to ask on the forum if you have any questions or feedback!
Highlights
- Reverse proxy: ✨ Dynamic upstreams, which is the ability to get the list of upstreams at every request (more specifically, every iteration in the proxy loop of every request) rather than just once at config-load time. Dynamic upstream modules can be plugged in to provide Caddy with the latest list of backends in real-time. Two standard modules have been implemented which can get upstreams from SRV and A/AAAA record lookups.
- ⚠️ This deprecates the
lookup_srv
JSON field for upstreams (andsrv+
scheme prefix in the Caddyfile), which will be removed in the future.
- ⚠️ This deprecates the
- Automatic HTTPS: Caddy will automatically try to get relevant certificates from the local Tailscale instance (if running with permission to access the Tailscale socket). This makes services running on a Tailscale network automatically available over trusted HTTPS with Caddy.
- Tracing: New OpenTelemetry integration with the
tracing
handler module and associatedtracing
directive. - Reverse proxy: When using the response handlers, a new handler
copy_response
is available to copy the proxy's response back to the client, andcopy_response_headers
may be used to selectively copy header values from the proxy's response. - API: Added new endpoints
/pki/ca/<id>
and/pki/ca/<id>/certificates
for getting information about Caddy's managed CAs, including the chain of root and intermediate certificates.
Notable
- Reverse proxy: The
X-Forwarded-Host
header will now be automatically set, along withX-Forwarded-For
andX-Forwarded-Proto
. - ⚠️ Reverse proxy: Incoming
X-Forwarded-*
headers will no longer be automatically trusted, to prevent spoofing. Now,trusted_proxies
must be configured to specify a list of downstream proxies which are trusted to have sent good values. You only need to configure trusted proxies if Caddy is not the first server being connected to. For example, if you have Cloudflare in front of Caddy, then you should configure this with Cloudflare's list of IP ranges. - Automatic HTTPS: Revoked certificates will be automatically replaced more reliably.
- Automatic HTTPS: Can now get certificates from Managers. As opposed to Issuers (such as the default ACME issuers) which give Caddy certificates to manage from a CSR, Managers give Caddy certificates to serve (rather than manage) during TLS handshakes.
- Automatic HTTPS: A DNS challenge domain override can be configured to delegate the solving of the challenge to a different domain.
- Reverse proxy: The default dial timeout for the HTTP transport has been adjusted down to
3s
(was10s
), which should allow for more easily configuring load balancing retries. - Logging: HTTP access logs will now render empty values for often-sensitive HTTP headers such as Cookie, Authorization, and Proxy-Authorization. Logging such credentials is now opt-in with the
log_credentials
global option in the Caddyfile, or the server'slogs > should_log_credentials
field in JSON. - Logging: Logs can now be filtered by query string parameters, cookie values, and regular expressions; and log values can be hashed. These features are useful for redacting sensitive information.
- Logging: Errors during request handling will now be logged at
DEBUG
level if the error was handled viaerrors
routes (handle_errors
in Caddyfile). - ⚠️ Logging: Removed the deprecated
common_log
field from HTTP access logs, and thesingle_field
encoder. If you relied on this, you may use the transform encoder plugin to encode logs in Common Log format. - ⚠️ Logging: The
remote_addr
field has been replaced byremote_ip
andremote_port
fields in HTTP access logs, which split up the two parts of the remote address. This improves ease of use for some tooling which only expect an IP address, without a port. - HTTP server: The
vars
matcher can now match on multiple possible values. - HTTP server: Requests can now be assigned a random and unique UUID from the new
{http.request.uuid}
placeholder. - HTTP server: New
http_redirect
listener wrapper which can be used to redirect HTTP requests that come in on a server listening for HTTPS requests to be redirected tohttps://
. - Caddyfile: New
default_bind
global option lets you specify the default interface all sockets should bind to. - Caddyfile: New
pki
global option lets you configure the properties of the internal CAs managed by Caddy. - Caddyfile: New
method
directive allows rewriting the request method via Caddyfile. - ⚠️ Caddyfile: The
reverse_proxy
directive'shandle_response
subdirective has had its status replacement functionality moved to a newreplace_status
subdirective. This makes sure that the functionality ofhandle_response
is not overloaded, and usage is clearer. - ⚠️ Admin: Renamed experimental property
load_interval
➡️load_delay
for clarification, and improved dynamic config loading.
🛡️ Thanks to David Leadbeater for reporting a security vulnerability related to HTTP methods and metrics cardinality, which was fixed in this release.
New Contributors
- @adamburgess made their first contribution in #4460
- @12f23eddde made their first contribution in #4444
- @rayjlinden made their first contribution in #4023
- @GallopingKylin made their first contribution in #4522
- @ForestJohnson made their first contribution in #4534
- @VojtechVitek made their first contribution in #4535
- @Ikke made their first contribution in #4544
- @YourTechBud made their first contribution in #4603
- @BitWuehler made their first contribution in #4597
- @ttys3 made their first contribution in #4572
- @crccw made their first contribution in #4596
- @andriikushch made their first contribution in #4361
- @renbou made their first contribution in #4654
- @cuishuang made their first contribution in #4702
Changelog
- 2e46c2a admin, reverseproxy: Stop timers if canceled to avoid goroutine leak (#4482)
- 40b5443 admin: Enforce and refactor origin checking
- b4bfa29 admin: Require identity for remote (fix #4478)
- 32aad90 admin: Write proper status on invalid requests (#4569) (fix #4561)
- ff137d1 caddyconfig: Support placeholders in HTTP loader
- b47af6e caddyfile: Copy input before parsing (fix #4422)
- e90d751 caddyfile: impove fmt warning message (#4444)
- 5e5af50 caddyfile: make renew_interval option configurable (#4451)
- ddbb234 caddyhttp: Always log handled errors at debug level (#4584)
- 6b385a3 caddyhttp: Don't attempt to manage Tailscale certs
- ecac03c caddyhttp: Enhance vars matcher (#4433)
- 6e6ce2b caddyhttp: Fix HTTP->HTTPS redir not preferring HTTPS port if ambiguous (#4530)
- 3fe2c73 caddyhttp: Fix
MatchPath
sanitizing (#4499) - 44e5e9e caddyhttp: Fix test when /tmp/etc already exists (#4544)
- 2bb8550 caddyhttp: Honor wildcard hosts in log SkipHosts (#4606)
- 180ae0c caddyhttp: Implement http.request.uuid placeholder (#4285)
- 7d5047c caddyhttp: Log empty value for typical password headers
- eead337 caddyhttp: Log non-500 handler errors at debug level (#4429)
- 5bf0ada caddyhttp: Make logging of credential headers opt-in (#4438)
- 186fdba caddyhttp: Move HTTP redirect listener to an optional module (#4585)
- 80d7a35 caddyhttp: Redirect HTTP requests on the HTTPS port to https:// (#4313)
- bf380d0 caddyhttp: Reject absurd methods (#4538)
- 850e160 caddyhttp: Return HTTP 421 for mismatched Host header (#4023)
- f55b123 caddyhttp: Split up logged remote address into IP and port (#4403)
- ac14b64 caddyhttp: Support zone identifiers in remote_ip matcher (#4597)
- a1c4121 caddypki: Minor tweak, don't use context pointer
- 78e381b caddypki: Refactor /pki/ admin endpoints
- c634bbe caddypki: Return error if no PEM data found
- 9b7cdfa caddypki: Try to fix lint warnings
- a79b405 caddytls: Add internal Caddyfile
lifetime
,sign_with_root
opts (#4513) - 66de438 caddytls: Fix
MatchRemoteIP
provisoning with multiple CIDR ranges (#4522) - 57a708d caddytls: Support external certificate Managers (like Tailscale) (#4541)
- d9b1d46 caddytls: dns_challenge_override_domain for challenge delegation (#4596)
- 1a7a78a cmd: Print error if fmt overwrite fails (fix #4524)
- bc447e3 core: Config LoadInterval -> LoadDelay for clarity
- 7ea5b2a core: Config load interval only reloads if changed (#4603)
- 7f364c7 core: Load config at interval instead of just once
- a72acd2 core: Retry dynamic config load if config unchanged
- ceef70d core: Retry dynamic config load if error or no-op (#4603)
- acbee94 core: Revert 7f364c7; simplify dynamic config load
- 64a3218 core: Simplify shared listeners, fix deadline bug
- 8e5aafa fastcgi: Fix a TODO, prevent zap using reflection for logging env (#4437)
- c8f2834 fastcgi: Protect against requests with null bytes in the path (#4614)
- de490c7 fastcgi: Set SERVER_PORT to 80 or 443 depending on scheme (#4572)
- 09ba9e9 fileserver: Add
pass_thru
Caddyfile option (#4613) - 15c95e9 fileserver: Canonical redir when whole path is stripped (#4549)
- c8b5a81 fileserver: Fix handling of symlink sizes in directory listings (#4415)
- e81369e fileserver: Move default browse template into a separate file (#4417)
- 1e10f6f fileserver: browse: do not encode the paths in breadcrumbs and page title (#4410)
- 78b5356 fileserver: do not double-escape paths (#4447)
- 0de5159 go.mod: Revert version bump of CEL (#4587)
- 6f9b6ad go.mod: Update smallstep/certificates, no longer need replace (#4475)
- 4906b93 go.mod: Update smallstep/truststore, fix build on FreeBSD (#4473)
- c133153 go.mod: Update to latest smallstep/truststore, support FreeBSD (#4453)
- ff74a0a go.mod: Upgrade dependencies
- e9dde23 headers: Fix
+
in Caddyfile to properly append rather than set (#4506) - 1b7ff5d httpcaddyfile: Add
default_bind
global option (#4531) - 5a07156 httpcaddyfile: Add pki app
root
andintermediate
cert/key config (#4514) - 26d633b httpcaddyfile: Disabling OCSP stapling for both managed and unmanaged (#4589)
- 93a7a45 httpcaddyfile: Fix incorrect handling of IPv6 bind addresses (#4532)
- 81ee34e httpcaddyfile: Fix sorting edgecase for nested
handle_path
(#4477) - 4b9849c httpcaddyfile: Support configuring
pki
app names via global options (#4450) - 5bd96a6 httpcaddyfile: Support explicitly turning off
strict_sni_host
(#4592) - c921e08 logging: Add
roll_local_time
Caddyfile option (#4583) - 0eb0b60 logging: Remove common_log field and single_field encoder (#4149) (#4282)
- 249adc1 logging: Support turning off roll compression via Caddyfile (#4505)
- 8887adb logging: add a filter for cookies (#4425)
- bcac2be logging: add a filter for query parameters (#4424)
- 789efa5 logging: add a regexp filter (#4426)
- a1b417c logging: add support for hashing data (#4434)
- eb891d4 metrics: Enforce smaller set of method labels
- c04d24c pki: Avoid provisioning the
local
CA when not necessary (#4463) - bbad693 pki: Implement API endpoints for certs and
caddy trust
(#4443) - 9ee68c1 reverseproxy: Adjust defaults, document defaults (#4436)
- 7557d1d reverseproxy: Avoid returning a
nil
error during GetClientCertificate (#4550) - ab04559 reverseproxy: Dynamic upstreams (with SRV and A/AAAA support) (#4470)
- 5333c35 reverseproxy: Fix incorrect
health_headers
Caddyfile parsing (#4485) - c50094f reverseproxy: Implement trusted proxies for
X-Forwarded-*
headers (#4507) - f5e1049 reverseproxy: Make shallow-ish clone of the request (#4551)
- 87a1f22 reverseproxy: Move status replacement intercept to
replace_status
(#4300) - d058dee reverseproxy: Refactor dial address parsing, augment command parsing (#4616)
- c7d6c4c reverseproxy: copy_response and copy_response_headers for handle_response routes (#4391)
- bcb7a19 rewrite: Add
method
Caddyfile directive (#4528) - 1feb659 rewrite: Fix a double-encode issue when using the
{uri}
placeholder (#4516) - 6cadb60 templates: Document .OriginalReq
- 1d0425b templates: Elaborate on what's supported by the markdown function (#4564)
- a6199cf templates: Fix docs for .Args
- ec14ccd templates: fix inconsistent nested includes (#4452)
- d0b608a tracing: New OpenTelemetry module (#4361)
- 134b805 caddyfile: Prevent bad block opening tokens (#4655)
- c5fffb4 caddyfile: Support for raw token values; improve
map
,expression
(#4643) - b82e22b caddyhttp: retain all values of vars matcher when specified multiple times (#4629)
- bc15b4b caddypki: Load intermediate for signing on-the-fly (#4669)
- 6512832 cmd: Add
--diff
option forcaddy fmt
(#4695) - 30b6d1f cmd: Enhance .env (dotenv) file parsing
- 22d8edb cmd: Fix defaulting admin address if empty in config, fixes
reload
(#4674) - c232716 cmd: Set Origin header properly on API requests
- d06d0e7 go.mod: Upgrade CertMagic to v0.16.0
- bf6a1b7 go.mod: Upgrade some dependencies
- 79cbe7b httpcaddyfile: Add 'vars' directive
- a58f240 httpcaddyfile: Fix #4640 (auto-HTTPS edgecase) (#4661)
- 7d22966 logging: Caddyfile support for
duration_format
(#4684) - 55b4c12 map: Evaluate placeholders in output vals (#4650)
- 93c99f6 map: Support numeric and bool types with Caddyfile
- 3d616e8 requestbody: Return HTTP 413 (fix #4558)
- 3e3bb00 reverseproxy: Add
_ms
placeholders for proxy durations (#4666) - 2196c92 reverseproxy: Don't clear name in SRV upstreams
- dc4d147 reverseproxy: Expand SRV/A addrs for cache key
- b8dbecb reverseproxy: Include port in A upstreams cache
- e4ce40f reverseproxy: Sync up
handleUpgradeResponse
with stdlib (#4664) - afca242 staticfiles: Expand placeholder for index files (#4679)
- 00234c8 templates: Switch to
BurntSushi/toml
(#4700)
Full Changelog: v2.4.6...v2.5.0-rc.1