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")
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.shbin/ncp/NETWORKING/freeDNS.shbin/ncp/NETWORKING/namecheapDNS.shbin/ncp/NETWORKING/dnsmasq.shbin/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
- On a working NCP instance with a real domain, confirm
overwriteprotocolishttps:ncc config:system:get overwriteprotocol - 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" - Inspect the result:
Observed:ncc config:system:get overwrite.cli.urlcloud.example.com://cloud.example.com/
Expected:https://cloud.example.com/ - 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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