Skip to content

fix(builtin): derive server mode and public URL from IURLGenerator rather than browser context#5639

Draft
joshtrichards wants to merge 19 commits intomainfrom
jtr/fix-setup-builtin-URLs
Draft

fix(builtin): derive server mode and public URL from IURLGenerator rather than browser context#5639
joshtrichards wants to merge 19 commits intomainfrom
jtr/fix-setup-builtin-URLs

Conversation

@joshtrichards
Copy link
Copy Markdown
Member

  • Resolves: #
  • Target version: main

Summary

The built-in CODE server (richdocumentscode) configuration had a cluster of related bugs rooted in a single misconception: the admin UI was constructing the CODE proxy URL client-side from window.location.host and using it for both detection and storage. This only worked by coincidence on the simplest single-host setups and broke silently under reverse proxies, split DNS, or any deployment where the internal and public URLs differ.

This PR fixes all related issues and takes advantage of CODE's ProxyPrefix mechanism — which makes the /hosting/discovery response request-context-aware — to establish a clean, correct architecture for both browser-based and CLI-based setup paths.


Bugs Fixed

Bug 1 — Builtin mode detection used a browser-constructed URL (AdminSettings.vue L834–835)

checkIfDemoServerIsActive() constructed CODEUrl from window.location.host + generateFilePath(...) and compared it to the server-stored wopi_url. These are conceptually different things that only matched by coincidence. Any reverse proxy or split DNS broke the comparison, causing the "builtin" radio button to never be selected even with a working CODE installation.

Bug 2 — setBuiltinServer() wrote a browser-constructed URL as wopi_url

wopi_url is the internal server-to-server URL; it must be derived from IURLGenerator server-side. Storing a browser-constructed value here caused Nextcloud to attempt internal connections via the public URL, which fails or performs unnecessarily in many network configurations.

Bug 3 — checkSettings() never re-evaluated serverMode

serverMode was determined once in beforeMount() from the initial state snapshot. checkSettings() fetched fresh settings asynchronously but never called checkIfDemoServerIsActive() afterwards, leaving the displayed radio button stale.

Bug 4 — autoConfigurePublicUrl() poisoned public_wopi_url in CLI context

For the built-in CODE server, public_wopi_url should always equal Nextcloud's own public origin — CODE has no separate hostname. But autoConfigurePublicUrl() derived it server-side from the discovery urlsrc, which for builtin CODE is request-context-aware via ProxyPrefix. In CLI context (occ), this reflected overwrite.cli.url (often internal/localhost) rather than the true public URL, causing SERVER_STATE_BROWSER_CONNECTION_ERROR even when the server-side connection was healthy.


Architecture Changes

server_mode is now first-class config

A new server_mode config key (builtin | custom | demo) is stored explicitly. The frontend reads it directly — no URL string comparison needed, no guessing.

wopi_url for builtin is derived at runtime, never stored

AppConfig::getCollaboraUrlInternal() now derives the proxy URL via IURLGenerator on every call for builtin mode. This means it automatically stays correct after domain migrations without reconfiguration.

public_wopi_url for builtin is derived from IURLGenerator, not discovery

For builtin, AppConfig::getCollaboraUrlPublic() returns domainOnly(IURLGenerator::getAbsoluteURL('/')) — Nextcloud's own public origin. This is correct in both HTTP and CLI contexts, provided overwrite.cli.url is set (a standard Nextcloud prerequisite already required for cron jobs, notifications, and other occ commands).

autoConfigurePublicUrl() is skipped for builtin

Since public_wopi_url is derived dynamically for builtin, discovery-based detection is neither needed nor correct. ConnectivityService::autoConfigurePublicUrl() is now a no-op when server_mode === 'builtin'.

Browser self-healing via ProxyPrefix

checkFrontend() now fetches /hosting/discovery directly (same-origin for builtin, fully readable) and extracts the urlsrc origin. Because CODE's ProxyPrefix mechanism rewrites urlsrc to reflect the request's host and scheme, the browser always receives the correct public origin. If it differs from the stored public_wopi_url (e.g. after a domain migration), it is persisted back to the server automatically.

CLI builtin setup via --builtin flag

occ richdocuments:activate-config now accepts --builtin. It derives both wopi_url and public_wopi_url from IURLGenerator, verifies internal connectivity, and fails fast with an actionable message if the derived URL looks internal (indicating overwrite.cli.url is not set correctly).


Changes

File Change
lib/AppConfig.php Add SERVER_MODE constant; inject IURLGenerator; add getServerMode(), isBuiltinServer(), getBuiltinServerUrl(); update getCollaboraUrlInternal() and getCollaboraUrlPublic() to derive values dynamically for builtin mode
lib/Service/ConnectivityService.php autoConfigurePublicUrl() returns early for builtin mode
lib/Controller/SettingsController.php Add server_mode and builtin_server_url to getSettingsData(); update setSettings() to accept and handle server_mode; activate builtin mode server-side via IURLGenerator
lib/Settings/Admin.php Expose server_mode and builtin_server_url in initial state
lib/Command/ActivateConfig.php Add --builtin flag with full builtin setup path; derive and validate public URL from IURLGenerator; fail fast with actionable error if URL looks internal
src/components/AdminSettings.vue Replace checkIfDemoServerIsActive() to read server_mode directly; replace setBuiltinServer() to delegate URL derivation to the server; fix checkSettings() to re-evaluate serverMode after async fetch; replace checkFrontend() with discovery-based self-healing for builtin; remove all client-side CODEUrl construction

Testing

Browser-based setup (fresh install):

  • Install richdocuments + richdocumentscode on a plain single-host setup; select "Built-in CODE"; verify server mode saved correctly and editor opens
  • Same behind a reverse proxy where the internal URL differs from the public URL; verify public_wopi_url is correctly detected via checkFrontend()
  • Reload admin settings page; verify "Built-in CODE" radio is pre-selected via server_mode from server

CLI-based setup:

  • occ richdocuments:activate-config --builtin with overwrite.cli.url correctly set; verify both URLs are correct
  • Same with overwrite.cli.url set to localhost; verify command fails fast with actionable error message
  • occ richdocuments:activate-config --wopi-url=... (custom server path); verify existing behaviour unchanged

Self-healing:

  • Change Nextcloud domain; reload admin settings; verify public_wopi_url is updated automatically without manual reconfiguration

Regression:

  • Custom/standalone Collabora configuration unaffected: server_mode=custom, autoConfigurePublicUrl() still runs, public_wopi_url still set from discovery
  • Demo server mode unaffected

TODO

  • ...

Checklist

  • Code is properly formatted
  • Sign-off message is added to all commits
  • Documentation (manuals or wiki) has been updated or is not required

Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
@joshtrichards joshtrichards added bug Something isn't working 2. developing Work in progress integration: built-in code server richdocumentscode setup labels May 7, 2026
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
…ing set

Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
…ctivity

Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2. developing Work in progress bug Something isn't working integration: built-in code server richdocumentscode setup

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant