1. The problem I’m having:
After updating caddy from 2.10.0 to 2.10.2 I’ve noticed that my Nextcloud had some issues, namely files not being displayed anymore. After digging deeper into it I’ve noticed a lot of requests to NC failing with status 400 that haven’t failed before. NC handles requests really weirdly and I’m almost sure that the issue is somewhere within my Caddyfile, but I’m not that familiar with Caddy yet to figure out whats wrong. I suspect that this PR changed some behavior which is why I’m seeing this issue. I am aware that I am not supposed to redact the domain names, I have chosen to do so anyway for my own protection. Sorry.
2. Error messages and/or full log output:
With 2.10.0 (working as intended):
2025/11/08 09:05:14.653 DEBUG http.handlers.file_server sanitized path join {"site_root": "/var/www/cloud.<DOMAIN REPLACED>", "fs": "", "request_path": "/remote.php/dav/files/aurora/", "result": "/var/www/cloud.<DOMAIN REPLACED>/remote.php/dav/files/aurora"}
2025/11/08 09:05:14.653 DEBUG http.handlers.rewrite rewrote request {"request": {"remote_ip": "<IP REPLACED>", "remote_port": "52548", "client_ip": "<IP REPLACED>", "proto": "HTTP/1.1", "method": "PROPFIND", "host": "cloud.<DOMAIN REPLACED>", "uri": "/remote.php", "headers": {"User-Agent": ["Mozilla/5.0 (Windows) mirall/4.0.1 (build 20251027) (Nextcloud, windows-10.0.26100 ClientArchitecture: x86_64 OsArchitecture: x86_64)"], "Accept": ["*/*"], "Content-Type": ["text/xml; charset=utf-8"], "Content-Length": ["105"], "Cookie": ["REDACTED"], "Connection": ["Keep-Alive"], "Accept-Encoding": ["zstd, br, gzip, deflate"], "Depth": ["0"], "Authorization": ["REDACTED"], "X-Request-Id": ["d4eb3f35-52ce-4581-8fce-799404e908f3"], "Accept-Language": ["de-AT,en,*"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "", "server_name": "cloud.<DOMAIN REPLACED>"}}, "method": "PROPFIND", "uri": "/remote.php"}
2025/11/08 09:05:14.653 DEBUG http.reverse_proxy.transport.fastcgi roundtrip {"dial": "/var/run/php-fpm/php-fpm.sock", "env": {"SCRIPT_FILENAME": "/var/www/cloud.<DOMAIN REPLACED>/remote.php", "HTTP_X_FORWARDED_HOST": "cloud.<DOMAIN REPLACED>", "REQUEST_SCHEME": "https", "PATH_TRANSLATED": "/var/www/cloud.<DOMAIN REPLACED>/dav/files/aurora", "SSL_CIPHER": "TLS_AES_128_GCM_SHA256", "front_controller_active": "true", "HTTP_ACCEPT": "*/*", "HTTP_ACCEPT_ENCODING": "zstd, br, gzip, deflate", "REQUEST_URI": "/remote.php/dav/files/aurora/", "HTTPS": "on", "REQUEST_METHOD": "PROPFIND", "SERVER_NAME": "cloud.<DOMAIN REPLACED>", "SERVER_SOFTWARE": "Caddy/v2.10.0", "DOCUMENT_ROOT": "/var/www/cloud.<DOMAIN REPLACED>", "HTTP_ACCEPT_LANGUAGE": "de-AT,en,*", "HTTP_DEPTH": "0", "CONTENT_LENGTH": "105", "PATH_INFO": "/dav/files/aurora", "SERVER_PORT": "443", "modHeadersAvailable": "true", "HTTP_CONTENT_TYPE": "text/xml; charset=utf-8", "HTTP_CONTENT_LENGTH": "105", "HTTP_X_FORWARDED_FOR": "<IP REPLACED>", "REMOTE_PORT": "52548", "SSL_PROTOCOL": "TLSv1.3", "AUTH_TYPE": "", "REMOTE_HOST": "<IP REPLACED>", "SCRIPT_NAME": "/remote.php", "GATEWAY_INTERFACE": "CGI/1.1", "REMOTE_IDENT": "", "QUERY_STRING": "", "REMOTE_ADDR": "<IP REPLACED>", "HTTP_X_FORWARDED_PROTO": "https", "HTTP_VIA": "1.1 Caddy", "HTTP_COOKIE": "", "CONTENT_TYPE": "text/xml; charset=utf-8", "DOCUMENT_URI": "/remote.php", "HTTP_AUTHORIZATION": "", "HTTP_USER_AGENT": "Mozilla/5.0 (Windows) mirall/4.0.1 (build 20251027) (Nextcloud, windows-10.0.26100 ClientArchitecture: x86_64 OsArchitecture: x86_64)", "HTTP_X_REQUEST_ID": "d4eb3f35-52ce-4581-8fce-799404e908f3", "REMOTE_USER": "", "SERVER_PROTOCOL": "HTTP/1.1", "HTTP_HOST": "cloud.<DOMAIN REPLACED>"}, "request": {"remote_ip": "<IP REPLACED>", "remote_port": "52548", "client_ip": "<IP REPLACED>", "proto": "HTTP/1.1", "method": "PROPFIND", "host": "cloud.<DOMAIN REPLACED>", "uri": "/remote.php", "headers": {"X-Forwarded-Host": ["cloud.<DOMAIN REPLACED>"], "Content-Type": ["text/xml; charset=utf-8"], "Content-Length": ["105"], "X-Forwarded-For": ["<IP REPLACED>"], "Accept-Encoding": ["zstd, br, gzip, deflate"], "X-Request-Id": ["d4eb3f35-52ce-4581-8fce-799404e908f3"], "Accept-Language": ["de-AT,en,*"], "X-Forwarded-Proto": ["https"], "Via": ["1.1 Caddy"], "Cookie": ["REDACTED"], "Depth": ["0"], "Authorization": ["REDACTED"], "User-Agent": ["Mozilla/5.0 (Windows) mirall/4.0.1 (build 20251027) (Nextcloud, windows-10.0.26100 ClientArchitecture: x86_64 OsArchitecture: x86_64)"], "Accept": ["*/*"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "", "server_name": "cloud.<DOMAIN REPLACED>"}}}
2025/11/08 09:05:14.684 DEBUG http.handlers.reverse_proxy upstream roundtrip {"upstream": "unix//var/run/php-fpm/php-fpm.sock", "duration": 0.03145498, "request": {"remote_ip": "<IP REPLACED>", "remote_port": "52548", "client_ip": "<IP REPLACED>", "proto": "HTTP/1.1", "method": "PROPFIND", "host": "cloud.<DOMAIN REPLACED>", "uri": "/remote.php", "headers": {"Accept-Language": ["de-AT,en,*"], "X-Forwarded-Proto": ["https"], "Via": ["1.1 Caddy"], "Cookie": ["REDACTED"], "Depth": ["0"], "Authorization": ["REDACTED"], "User-Agent": ["Mozilla/5.0 (Windows) mirall/4.0.1 (build 20251027) (Nextcloud, windows-10.0.26100 ClientArchitecture: x86_64 OsArchitecture: x86_64)"], "Accept": ["*/*"], "X-Forwarded-Host": ["cloud.<DOMAIN REPLACED>"], "Content-Type": ["text/xml; charset=utf-8"], "Content-Length": ["105"], "X-Forwarded-For": ["<IP REPLACED>"], "Accept-Encoding": ["zstd, br, gzip, deflate"], "X-Request-Id": ["d4eb3f35-52ce-4581-8fce-799404e908f3"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "", "server_name": "cloud.<DOMAIN REPLACED>"}}, "headers": {"Status": ["207 Multi-Status"], "Content-Security-Policy": ["default-src 'none';"], "Vary": ["Brief,Prefer"], "X-Request-Id": ["lottBP7cmair46GODy6V"], "X-Debug-Token": ["lottBP7cmair46GODy6V"], "Content-Encoding": ["gzip"], "X-Powered-By": ["PHP/8.4.14"], "Content-Type": ["application/xml; charset=utf-8"], "Dav": ["1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, nc-paginate, nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar"]}, "status": 207}
With 2.10.2 (broken):
2025/11/08 09:07:26.797 DEBUG http.handlers.file_server sanitized path join {"site_root": "/var/www/cloud.<DOMAIN REPLACED>", "fs": "", "request_path": "/remote.php/dav/files/aurora/", "result": "/var/www/cloud.<DOMAIN REPLACED>/remote.php/dav/files/aurora"}
2025/11/08 09:07:26.797 DEBUG http.log.error invalid argument {"request": {"remote_ip": "<IP REPLACED>", "remote_port": "52702", "client_ip": "<IP REPLACED>", "proto": "HTTP/2.0", "method": "REPORT", "host": "cloud.<DOMAIN REPLACED>", "uri": "/remote.php/dav/files/aurora/", "headers": {"Depth": ["1"], "Origin": ["https://cloud.<DOMAIN REPLACED>"], "Content-Type": ["text/plain;charset=UTF-8"], "Content-Length": ["652"], "Sec-Gpc": ["1"], "Sec-Fetch-Mode": ["cors"], "Cookie": ["REDACTED"], "Accept": ["text/plain,application/xml"], "Requesttoken": ["lqHCCvdnwoXmYd3X5rRrAvZalcY482i4N0JA4dO9/zU=:wJWwa5sPusCPAI6VnoUbdYQX5fNAnEeOfCdvk6XIj3Y="], "Pragma": ["no-cache"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:144.0) Gecko/20100101 Firefox/144.0"], "Sec-Fetch-Site": ["same-origin"], "X-Requested-With": ["XMLHttpRequest"], "Dnt": ["1"], "Accept-Language": ["de,en-US;q=0.7,en;q=0.3"], "Te": ["trailers"], "Accept-Encoding": ["gzip, deflate, br, zstd"], "Cache-Control": ["no-cache"], "Sec-Fetch-Dest": ["empty"], "Priority": ["u=4"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "h2", "server_name": "cloud.<DOMAIN REPLACED>"}}, "duration": 0.000134878, "status": 400, "err_id": "nccg40pkc", "err_trace": "fileserver.(*FileServer).ServeHTTP (staticfiles.go:308)"}
This doesn’t seem to be a browser-specific problem, as the NC desktop client and android app also have the same issue. The browser itself doesn’t show anything in the log beside getting 400 returned for that specific request, without any additional content. The request doesn’t reach NC, so that obviously also doesn’t show anything in its logs.
3. Caddy version:
v2.10.0 and v2.10.2
4. How I installed and ran Caddy:
a. System environment:
Arch 6.12.57-1-lts, caddy installed via pacman and run via systemd using the default service file: caddy.service · main · Arch Linux / Packaging / Packages / caddy · GitLab
b. Command:
see a
c. Service/unit/compose file:
n/a
d. My complete Caddy config:
In /etc/caddy/Caddyfile:
{
debug
admin "unix//run/caddy/admin.socket"
email <EMAIL REPLACED>
log default {
output file /var/log/caddy/caddy.log {
mode 644
roll_size 10MiB
}
format console
}
}
(php) {
php_fastcgi unix//var/run/php-fpm/php-fpm.sock
}
import /etc/caddy/conf.d/*
and in /etc/caddy/conf.d/cloud.<DOMAIN REPLACED>
cloud.<DOMAIN REPLACED> {
request_body {
max_size 10G
}
encode {
zstd
gzip 4
minimum_length 256
match {
header Content-Type application/atom+xml
header Content-Type application/javascript
header Content-Type application/json
header Content-Type application/ld+json
header Content-Type application/manifest+json
header Content-Type application/rss+xml
header Content-Type application/vnd.geo+json
header Content-Type application/vnd.ms-fontobject
header Content-Type application/wasm
header Content-Type application/x-font-ttf
header Content-Type application/x-web-app-manifest+json
header Content-Type application/xhtml+xml
header Content-Type application/xml
header Content-Type font/opentype
header Content-Type image/bmp
header Content-Type image/svg+xml
header Content-Type image/x-icon
header Content-Type text/cache-manifest
header Content-Type text/css
header Content-Type text/plain
header Content-Type text/vcard
header Content-Type text/vnd.rim.location.xloc
header Content-Type text/vtt
header Content-Type text/x-component
header Content-Type text/x-cross-domain-policy
}
}
header Referrer-Policy no-referrer
header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;"
header X-Content-Type-Options nosniff
header X-Download-Options noopen
header X-Frame-Options SAMEORIGIN
header X-Permitted-Cross-Domain-Policies none
header X-Robots-Tag noindex,nofollow
root * /var/www/cloud.<DOMAIN REPLACED>
file_server
route {
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
@msftdavclient {
header User-Agent DavClnt*
path /
}
redir @msftdavclient /remote.php/webdav/ temporary
route /robots.txt {
skip_log
file_server
}
# Add exception for `/.well-known` so that clients can still access it
# despite the existence of the `error @internal 404` rule which would
# otherwise handle requests for `/.well-known` below
route /.well-known/* {
redir /.well-known/carddav /remote.php/dav/ permanent
redir /.well-known/caldav /remote.php/dav/ permanent
@well-known-static path \
/.well-known/acme-challenge /.well-known/acme-challenge/* \
/.well-known/pki-validation /.well-known/pki-validation/*
route @well-known-static {
try_files {path} {path}/ =404
file_server
}
redir * /index.php{path} permanent
}
@internal path \
/build /build/* \
/tests /tests/* \
/config /config/* \
/lib /lib/* \
/3rdparty /3rdparty/* \
/templates /templates/* \
/data /data/* \
\
/.* \
/autotest* \
/occ* \
/issue* \
/indie* \
/db_* \
/console*
error @internal 404
@assets {
path *.css *.js *.svg *.gif *.png *.jpg *.jpeg *.ico *.wasm *.tflite *.map *.wasm2
file {path} # Only if requested file exists on disk, otherwise /index.php will take care of it
}
route @assets {
header /* Cache-Control "max-age=15552000" # Cache-Control policy borrowed from `.htaccess`
header /*.woff2 Cache-Control "max-age=604800" # Cache-Control policy borrowed from `.htaccess`
skip_log # Optional: Don't log access to assets
file_server {
precompressed gzip
}
}
# Rule borrowed from `.htaccess`
redir /remote/* /remote.php{path} permanent
# Serve found static files, continuing to the PHP default handler below if not found
try_files {path} {path}/
@notphpordir not path /*.php /*.php/* / /*/
file_server @notphpordir {
pass_thru
}
# Required for legacy support
#
# Rewrites all other requests to be prepended by “/index.php” unless they match a known-valid PHP file path.
@unknownphppath not path \
/index.php /index.php/* \
/remote.php /remote.php/* \
/public.php /public.php/* \
/cron.php /cron.php/* \
/core/ajax/update.php /core/ajax/update.php/* \
/status.php /status.php/* \
/ocs/v1.php /ocs/v1.php/* \
/ocs/v2.php /ocs/v2.php/* \
/updater/*.php /updater/*.php/* \
/ocm-provider/*.php /ocm-provider/*.php/* \
/ocs-provider/*.php /ocs-provider/*.php/* \
/*/richdocumentscode/proxy.php /*/richdocumentscode/proxy.php/*
rewrite @unknownphppath /index.php{path}
php_fastcgi unix//var/run/php-fpm/php-fpm.sock {
env modHeadersAvailable true # Avoid sending the security headers twice
env front_controller_active true # Enable pretty urls
}
}
}
5. Links to relevant resources:
The Nextcloud caddy config has been pretty much copied from this pull request: Add complete Caddy sample configuration inspired by the NGINX one by ntninja · Pull Request #9199 · nextcloud/documentation · GitHub