Skip to content

set-nc-domain() sets overwrite.cli.url to malformed domain://domain/ when called with a bare domain, breaking notify_push ("malformed server url") #2129

Description

@89217431

Bug description

When set-nc-domain() in etc/library.sh is called with a bare domain that has no scheme prefix (e.g. cloud.example.com instead of https://cloud.example.com), it writes a malformed value into overwrite.cli.url of the form domain://domain/, for example:

overwrite.cli.url = cloud.example.com://cloud.example.com/

This malformed URL propagates into the notify_push / High Performance Backend setup, whose self-test then aborts with:

🗴 malformed server url

The HPB service stays down until the value is corrected by hand. Because library.sh is replaced on every ncp-update, any local fix is reverted and the failure recurs after each update.

Root cause

The function begins with:

function set-nc-domain()
{
  local domain="${1?}"
  local proto="${domain%://*}"
  domain="${domain#*://}" #strip protocol
  ...
  [[ -n "$proto" ]] || proto="$(ncc config:system:get overwriteprotocol)" || true
  ...
  local url="${proto:-https}://${host%/*}${port:-}"
  ...
  ncc config:system:set overwrite.cli.url --value="${url}/"

The parameter expansion ${domain%://*} removes the shortest suffix matching ://*. When the input contains no ://, there is nothing to strip, so the expansion returns the input unchanged. As a result proto is set to the domain itself instead of a protocol.

The existing fallback on the next relevant line does not rescue this, because it only fires when proto is empty:

[[ -n "$proto" ]] || proto="$(ncc config:system:get overwriteprotocol)"

Here proto is non-empty (it wrongly holds the domain), so overwriteprotocol is never consulted, even when it is correctly set to https. The URL is then assembled as ${proto}://${host}, which becomes domain://domain, and is saved with a trailing slash as domain://domain/.

Note: in the code path where the host is not reachable, proto, domain, host and port are unset, which lets the overwriteprotocol fallback work correctly. The malformed result therefore appears specifically when the bare host is resolvable and pingable, so proto retains the domain value. This is why the bug shows up on working, live domains.

Affected callers

Multiple callers pass a bare $DOMAIN without a scheme, so all of them can trigger the malformed value:

  • bin/ncp/NETWORKING/letsencrypt.sh (runs on every certificate renewal via the deploy hook)
  • bin/nextcloud-domain.sh (runs on password reset, restore, and nc-init)
  • bin/ncp/NETWORKING/no-ip.sh
  • bin/ncp/NETWORKING/freeDNS.sh
  • bin/ncp/NETWORKING/namecheapDNS.sh
  • bin/ncp/NETWORKING/dnsmasq.sh
  • bin/ncp-update-nc.d/update-nc.sh

Because letsencrypt.sh runs on certificate renewal, the value is silently re-corrupted at renewal time even if it was previously repaired.

Steps to reproduce

  1. On a working NCP instance with a real domain, confirm overwriteprotocol is https:
    ncc config:system:get overwriteprotocol
    
  2. Trigger any scheme-less caller. For example run a Let's Encrypt renewal, or call the function directly:
    source /usr/local/etc/library.sh
    set-nc-domain "cloud.example.com"
    
  3. Inspect the result:
    ncc config:system:get overwrite.cli.url
    
    Observed: cloud.example.com://cloud.example.com/
    Expected: https://cloud.example.com/
  4. notify_push setup then fails:
    🗴 malformed server url
    

Expected behaviour

set-nc-domain() should treat a bare domain as having no scheme, leave proto empty in that case, and let the overwriteprotocol fallback supply the correct protocol. The resulting overwrite.cli.url should be https://domain/.

Suggested fix

Only treat the leading segment as a protocol when the input actually contains ://:

local proto=""
[[ "$domain" == *"://"* ]] && proto="${domain%%://*}"

With this guard, a bare domain leaves proto empty, the existing overwriteprotocol fallback fires, and the URL is assembled correctly. Inputs that do include a scheme continue to parse as before, so all current callers remain compatible.

Environment

  • NextcloudPi version: v1.58.0
  • Image: NextcloudPi_lxc (LXC on Proxmox)
  • OS: Debian GNU/Linux 13 (trixie)
  • Nextcloud version: 33.0.6.2
  • notify_push / HPB: enabled

Additional context

The malformed server url string itself is emitted by the notify_push app in lib/SelfTest.php; notify_push is only the messenger. The defect that produces the invalid URL is entirely in NextcloudPi's set-nc-domain().

This looks related in class to the earlier overwrite.cli.url issues (#2087, #2099, #2057), all of which involve overwrite.cli.url being set to an unexpected or invalid value, but the doubled domain://domain manifestation and its parsing root cause do not appear to be documented in any of them. The activation-page change from #2087 (v1.57.0) does not touch this parsing line.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions