nextcloud / nextcloud/nextcloudpi

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

Open Beginner friendly
#2,129 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Shell
Stars
2.9k
Forks
318
PR merge metrics
No merged PRs in 30d

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in etc/library.sh at set-nc-domain(), then reproduce with source /usr/local/etc/library.sh and a bare domain such as cloud.example.com. Check overwriteprotocol and overwrite.cli.url with ncc config:system:get. Done means bare domains produce a valid protocol-based URL while scheme-prefixed inputs remain compatible.

Written by the indexing model from the issue text.

Assessment

Tech stack
shell
Domain
devops
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.