Skip to content

fix: issue the DAV discovery redirects with the client's real scheme - #138

Merged
MattDHill merged 1 commit into
masterfrom
fix/dav-well-known-scheme
Sep 1, 2026
Merged

fix: issue the DAV discovery redirects with the client's real scheme#138
MattDHill merged 1 commit into
masterfrom
fix/dav-well-known-scheme

Conversation

@MattDHill

Copy link
Copy Markdown
Member

Closes #137.

What was actually broken

Only one of the three legs #137 diagnosed. Investigated against the OS source at start-os/v0.4.0.1 and verified live on a 0.4.0.1 box:

  1. addXForwardedHeaders is already enabled. SDK 2.0.9's knownProtocols defaults it on for http bindings, both released package versions shipped that SDK, and the live binding record carries "addXForwardedHeaders": true. The OS honors it on both the wildcard (LAN nonstandard-port) and domain vhosts.
  2. trusted_proxies is already set and effective. The proxy dials the container from 10.0.3.1, inside the modeled 10.0.3.0/24; the image's mod_remoteip is inert (its conf reads X-Real-IP, which nothing sends). PHP-generated URLs are already per-request correct — / redirects to https://…/login over TLS with no overwriteprotocol set.
  3. The remaining defect is Apache's own .htaccess redirects, which absolutize from Apache's connection scheme — always http behind the TLS-terminating proxy: /.well-known/carddav, /.well-known/caldav, and (missed in DAV autodiscovery broken behind the 0.4 proxy: Apache emits an http:// well-known redirect (macOS/iOS "account adds but never syncs" / "unable to verify") #137) the DavClnt user-agent redirect on /. On an https-only address the redirect target answers nothing, so Apple's Manual-mode account setup verified credentials and then dead-ended — "adds fine, never syncs."

The issue's proposed part 3 (neutralize the htaccess rules, fall through to PHP) cannot work: Nextcloud registers PHP well-known handlers only for webfinger/nodeinfo. There is no CardDAV/CalDAV handler — /index.php/.well-known/carddav returns 404 — so removing the rules trades a wrong-scheme redirect for a hard 404.

The fix

  • startos-dav-redirects.conf, baked into the image: scheme-aware duplicates of the three redirects in <Directory /var/www/html> under RewriteOptions InheritDownBefore, so they run ahead of the volume's stock .htaccess. With the proxy's X-Forwarded-Proto: https present they issue https:// redirects; without it (a plain-http/onion binding) they skip and stock behavior applies. The header is trustworthy on TLS bindings because the proxy strips any client-supplied value before injecting its own; on a plain binding a client forging it only mis-redirects itself, with no cache in the path.
    • A conf rather than an .htaccess patch is load-bearing: the entrypoint rsyncs /usr/src/nextcloud/ onto the volume only on an image version change, so a patched .htaccess would never reach installs already on this Nextcloud version. The conf lives in the image and applies on a plain package update, no migration.
    • mod_headers was tried and cannot do this: a 3xx's Location sits in headers_out, and on non-2xx responses only the always (err_headers_out) directives run — Header [always] edit Location provably never touches it.
  • APACHE_DISABLE_REWRITE_IP=1: pins mod_remoteip off. Today it is harmless by accident (wrong header name); if a future image read X-Forwarded-For it would rewrite REMOTE_ADDR to the client IP, trusted_proxies would stop matching, and the entire scheme/client-IP chain would silently regress.
  • overwriteprotocol stays modeled as null, now with the rationale in a comment: scheme truth is per-request via the forwarded header, and a blanket https would corrupt URLs on plain-http bindings.
  • README documents the scheme model with a one-line curl diagnostic; release notes gain the fix bullet in all five locales; version 34.0.3:1 → 34.0.3:2 (:1 is permanent on beta and prod).

Verified on StartOS 0.4.0.1 (34.0.3:2 built and installed as an in-place update from :1)

Probe Result
/.well-known/{carddav,caldav} — LAN https, nonstandard port 301 https://…/remote.php/dav/
Same — tunnel domain vhost (*.start9.dev) 301 https://…/remote.php/dav/
/ with DavClnt UA, both TLS legs 302 https://…/remote.php/webdav/
Plain-http leg (onion analog) 301 http://… — unchanged
Discovery → authenticated PROPFIND 207
occ setupchecks → WellKnownUrls success
Forged X-Forwarded-Proto on the plain port self-inflicted https redirect only

Answers to #137's open questions: trusted_proxies needs no change (10.0.3.0/24 matches the proxy's bridge source, and only the proxy or sibling containers can occupy it); no keep-alive interplay with #3731 arises because the binding is untouched — the HTTP-aware proxy path was already active; onion/plain bindings keep correct http URLs (verified); no OS/SDK version gate is needed — on an OS that didn't inject the header the new rules simply never fire and behavior is today's.

🤖 Generated with Claude Code

… 34.0.3:1 -> 34.0.3:2

Apache builds the Location of its .htaccess redirects from its own
connection scheme, which behind the TLS-terminating StartOS proxy is
always http. So /.well-known/carddav, /.well-known/caldav, and the
DavClnt user-agent redirect on / all sent clients to an http:// URL,
which on an https-only address (the normal 0.4 LAN binding) nothing
answers. macOS/iOS account setup walks exactly that endpoint: the
account verified but never synced (#137).

The rest of the chain already worked: SDK 2.0.9 defaults
addXForwardedHeaders on for http bindings, StartOS 0.4.0.1 injects
X-Forwarded-Proto/-For on TLS vhosts, and config.php's trusted_proxies
(10.0.3.0/24) makes Nextcloud honor them — PHP-generated URLs were
already per-request correct. And the issue's proposed htaccess
neutralization cannot work: Nextcloud has no PHP well-known handler for
carddav/caldav (only webfinger/nodeinfo), so falling through to
index.php returns 404.

So the fix duplicates the three redirects scheme-aware in an Apache
conf baked into the image: <Directory /var/www/html> rules under
RewriteOptions InheritDownBefore run ahead of the volume's stock
.htaccess, issue https:// redirects when the proxy's X-Forwarded-Proto
says https, and fall through to stock behavior on plain-http (onion)
bindings. A conf rather than an .htaccess patch is what reaches
installs whose volume already carries this Nextcloud version — the
entrypoint only rsyncs on a version change. mod_headers cannot do it:
a 3xx's Location lives in the one header table Header edit never
processes (verified empirically).

APACHE_DISABLE_REWRITE_IP=1 pins the image's mod_remoteip off. It is
inert today only because its conf reads X-Real-IP, which nothing
sends; were a future image to read X-Forwarded-For, it would rewrite
REMOTE_ADDR out of trusted_proxies range and silently break the whole
scheme/client-IP chain.

Verified on StartOS 0.4.0.1: carddav/caldav/DavClnt 301/302 to https
on both the LAN wildcard vhost (nonstandard port) and a tunnel domain
vhost; plain-http leg unchanged; discovery-then-PROPFIND 207; occ
setupchecks well-known success; update-in-place from 34.0.3:1.

Closes #137

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MattDHill
MattDHill merged commit 41d69b2 into master Sep 1, 2026
3 checks passed
@MattDHill
MattDHill deleted the fix/dav-well-known-scheme branch September 1, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant