Fix in-container upgrade failures by patching start.sh tar flags#20
Fix in-container upgrade failures by patching start.sh tar flags#20decriptor wants to merge 2 commits into
Conversation
…lity In-container Roon Server upgrades are silently failing for users with restricted-chown host setups (userns-remap, NFS root_squash, TrueNAS / Synology bind mounts with strict ACLs). Initial install works because entrypoint.sh extracts with `tar xjf ... --no-same-permissions --no-same-owner`, but RoonServer's bundled start.sh handles in-container upgrades with bare `tar xf "$PKG"`. The build tarballs ship with files owned by uid 1001 (the Azure Pipelines build agent), so when start.sh runs as root and tries to chown extracted files to 1001 on a host that rejects foreign-uid chown, tar exits non-zero and start.sh's `|| doerror` reports "ERROR: failed to tar xf $PKG". The user is left on the old version with no obvious diagnostic. The proper fix is upstream — start.sh should use the same flags entrypoint.sh uses. While that's pending, patch the on-disk start.sh from our entrypoint to inject the missing flags. Idempotent: skipped when the flag is already present, so it survives upstream's eventual fix without conflict, and re-runs after every successful upgrade (which restores start.sh from the new build tarball). Tests: pre-seed an existing install with an upstream-shape start.sh, run the entrypoint, assert the patched line is present and that the flag count is exactly 1 (not double-applied). Second test pre-seeds with an already-patched start.sh and asserts the log message is absent (idempotency on second pass). Smoke suite: 56 → 60 checks.
There was a problem hiding this comment.
Pull request overview
This PR addresses in-container Roon Server upgrade failures on filesystems/hosts where chown is restricted by ensuring the upgrade extraction in RoonServer/start.sh uses tar flags that avoid preserving owner/permissions from the build artifact.
Changes:
- Patch the on-disk
RoonServer/start.shat container startup to add--no-same-owner --no-same-permissionsto itstar xf "$PKG"invocation. - Add smoke tests that seed an “upstream-shaped”
start.sh, verify the patch is applied exactly once, and verify patching is skipped when already present.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
entrypoint.sh |
Adds an idempotent sed-based patch step that injects tar flags into RoonServer/start.sh to make upgrades resilient on restricted-chown hosts. |
tests/smoke.sh |
Adds smoke checks that validate patching behavior, idempotency, and logging. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two fixes from PR review on #20: - entrypoint.sh: patch guard now requires BOTH --no-same-owner AND --no-same-permissions before considering start.sh already patched. A partial upstream fix (one flag added, the other missing) would otherwise leave the file half-fixed with our patch silently skipped. Post-sed verification checks both flags before logging success. - smoke.sh: assert exit==0 on the second-run idempotency check. The previous version let \`|| true\` mask container startup failures, which would have made the negative "no log" assertion pass for the wrong reason. Now: capture exit code, assert it's 0, then assert the log is absent — so the negative assertion only triggers when the container actually ran cleanly.
|
i'm not 100% sure this will be enough; during my troubleshooting i noticed that patching Roon 2.64 's RoonServer/start.sh script was not enough; with patched start.sh , triggering an update from one of my Remotes still failed; from what i can tell, when triggered from a Roon Remote, Roon is not using /Roon/app/RoonServer/start.sh to upgrade itself, but a version extracted from the tar.bz2 archive ; that's why i ended up upgrading Roon manually (with command: docker exec 553609b4306f /Roon/app/RoonServer/start.sh --update /tmp/RoonServer_linuxx64.tar.bz2 /Roon/app/RoonServer)
|
|
I'm wondering if it's possible to fix how the tarball is built in the Azure pipeline. Something like: tar --owner=0 --group=0 --numeric-owner -cjf RoonServer_linuxx64.tar.bz2 RoonServer/ Right now, the build is leaking a bad userid into the tarball. This fixes that and I think it might work with no changes to either entrypoint.sh or start.sh. You should be able to drop the --no-same-owner flag from entrypoint.sh. There's a good chance you never needed the --no-same-permissions flag. If you actually do, it either needs to be retained in entrypoint + added to start.sh or the tree needs to be cleaned before it gets tarballed. I'm just suggesting this as an approach because it seems a lot cleaner to try to address this at the source rather than patch files with sed or whatever after they're installed. |
|
@gtunes-dev Agreed! I didn't mean to actually push this branch/PR yet. I was toying around with this to see if I could create a quick "patch" for the current image. I'm definitely planning on fixing the build. :) |
It's going to be tricky for some of your users to install an updated image. The build fix hopefully will just work. But...I'm not 100% sure what the change I proposed will actually do in all situations and on all linux platforms. I think it would work. I'm also thinking about what happens in the future if you ever want to support running as non-root and I think it will work in those situations, too. Like I said, though, not 100% on any of it. BTW - running as non root I think works like this in the container-based approach:
I think the change I'm suggesting to the tarball is ok with this approach for self updates done by start.sh. Because self updates will happen as either root or user-specified user, the tar (with no flags) of the clean tarball should result in files either all as root or as the user-specified user. Should just work. I hope :) Just saying this stuff for the record so that the clean tarball approach is seen as forward facing :) |
|
until we fix the issue at source, as gtunes-dev suggested, i found another possible solution on QNAP's forum - EFAULT (Bad address) error during file extraction in Container Station 3:
|
|
ok, I've created a fix in our code. I'm going to close this out because we should have a hotfix out soon with a couple other changes. |
Summary
Users on hosts with restricted-chown semantics (userns-remap Docker daemons, NFS bind mounts with
root_squash, TrueNAS / Synology bind mounts with strict ACLs) report that in-container Roon Server upgrades fail silently, leaving them stuck on whatever version was installed at first start. Initial install works fine.The reporter on a recent support ticket nailed the cause:
entrypoint.shextracts withtar xjf ... --no-same-permissions --no-same-owner, but RoonServer's bundledstart.sh(which handles in-container upgrades) uses baretar xf "$PKG". The build tarball stores files asvsts_azpcontainer:vsts_azpcontainer(uid1001, the Azure Pipelines build agent). When start.sh runs as root in a container whose host filesystem rejectschown 1001:1001, tar exits non-zero, start.sh's|| doerrorreports"ERROR: failed to tar xf $PKG", and the upgrade aborts.Mechanism (verified)
entrypoint.sh)start.sh)--no-same-ownermakes tar use container's effective uid--no-same-ownersidesteps the chowntar xftrieschown 1001outside the userns mapping → EPERM → exit non-zeroConfirmed by extracting the upstream tarball in a roonserver:1.0.6 container and inspecting
tar tjvf --numeric-owneroutput (uid 1001) andstart.sh:21(baretar xf).What this PR does
entrypoint.shnow patchesRoonServer/start.shafter the install block to inject--no-same-owner --no-same-permissionsinto its tar invocation. The patch is:! grep -q -- "--no-same-owner", so it skips when already applied (own past run, or upstream's eventual fix).|| doerrorwould surface a new failure if any). The grep guard covers both the "already patched" case and "upstream now has the flag".The proper fix is upstream —
start.shshould matchentrypoint.sh's flags. This PR is the in-image workaround until that lands.Test plan
tests/smoke.shextended (56 → 60 checks):tar xf "$PKG"correctlyroonserver:testbuild