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:
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
- On a working NCP instance with a real domain, confirm
overwriteprotocol is https:
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:
ncc config:system:get overwrite.cli.url
Observed: cloud.example.com://cloud.example.com/
Expected: https://cloud.example.com/
- notify_push setup then fails:
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.
Bug description
When
set-nc-domain()inetc/library.shis called with a bare domain that has no scheme prefix (e.g.cloud.example.cominstead ofhttps://cloud.example.com), it writes a malformed value intooverwrite.cli.urlof the formdomain://domain/, for example:This malformed URL propagates into the notify_push / High Performance Backend setup, whose self-test then aborts with:
The HPB service stays down until the value is corrected by hand. Because
library.shis replaced on everyncp-update, any local fix is reverted and the failure recurs after each update.Root cause
The function begins with:
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 resultprotois 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
protois empty:Here
protois non-empty (it wrongly holds the domain), sooverwriteprotocolis never consulted, even when it is correctly set tohttps. The URL is then assembled as${proto}://${host}, which becomesdomain://domain, and is saved with a trailing slash asdomain://domain/.Note: in the code path where the host is not reachable,
proto,domain,hostandportare unset, which lets theoverwriteprotocolfallback work correctly. The malformed result therefore appears specifically when the bare host is resolvable and pingable, soprotoretains the domain value. This is why the bug shows up on working, live domains.Affected callers
Multiple callers pass a bare
$DOMAINwithout 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.shBecause
letsencrypt.shruns on certificate renewal, the value is silently re-corrupted at renewal time even if it was previously repaired.Steps to reproduce
overwriteprotocolishttps:cloud.example.com://cloud.example.com/Expected:
https://cloud.example.com/Expected behaviour
set-nc-domain()should treat a bare domain as having no scheme, leaveprotoempty in that case, and let theoverwriteprotocolfallback supply the correct protocol. The resultingoverwrite.cli.urlshould behttps://domain/.Suggested fix
Only treat the leading segment as a protocol when the input actually contains
://:With this guard, a bare domain leaves
protoempty, the existingoverwriteprotocolfallback 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
Additional context
The
malformed server urlstring itself is emitted by the notify_push app inlib/SelfTest.php; notify_push is only the messenger. The defect that produces the invalid URL is entirely in NextcloudPi'sset-nc-domain().This looks related in class to the earlier
overwrite.cli.urlissues (#2087, #2099, #2057), all of which involveoverwrite.cli.urlbeing set to an unexpected or invalid value, but the doubleddomain://domainmanifestation 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.