release(v1.7.40-alpha): fix tarball root perms at source so OTA can't 500 again
v1.7.38 and v1.7.39 both shipped with `./` inside the frontend tarball marked drwx------ (700). Tar extraction preserves archive perms, so every node that pulled the OTA landed with /opt/archipelago/web-ui at 700, nginx (www-data) returned 500 "permission denied" on every page, and the browser showed "Internal Server Error nginx". .116 hit this on both v1.7.38 and v1.7.39 rollouts. The v1.7.39 runtime self-heal in main.rs was the wrong layer — systemd's ReadOnlyPaths namespace made /opt/archipelago read-only from inside the archipelago service, so chmod from there returned EROFS. Root cause: create-release-manifest.sh used mktemp -d (700 default umask) for staging, then tar preserved that 700 in the archive's root entry. Fix the archive itself: - chmod 755 staging dir + `find -type d -exec chmod 755` + `-type f chmod 644` before tar, so the on-disk entries are correct. - tar --owner=0 --group=0 --mode='u=rwX,go=rX' to normalize archive perms belt-and-braces in case file-mode drift ever reappears. - Post-tar verify: `tar tvzf | head -1` must show drwxr-xr-x at root, or the release script aborts before the manifest is even generated. Binary unchanged semantically — the main.rs self-heal stays in as a last- resort belt (can't hurt on nodes whose FS isn't namespace-isolated), and the update.rs in-extractor chmod stays in so v1.7.40-onwards extractors are double-safe. The authoritative fix is the archive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b8d084368e
commit
85417de952
2
core/Cargo.lock
generated
2
core/Cargo.lock
generated
@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.39-alpha"
|
version = "1.7.40-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"archipelago-container",
|
"archipelago-container",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.39-alpha"
|
version = "1.7.40-alpha"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Archipelago Bitcoin Node OS - Native backend"
|
description = "Archipelago Bitcoin Node OS - Native backend"
|
||||||
authors = ["Archipelago Team"]
|
authors = ["Archipelago Team"]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.7.39-alpha",
|
"version": "1.7.40-alpha",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "./start-dev.sh",
|
"start": "./start-dev.sh",
|
||||||
|
|||||||
@ -180,6 +180,16 @@ init()
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
||||||
|
<!-- v1.7.40-alpha -->
|
||||||
|
<div>
|
||||||
|
<div class="flex items-center gap-2 mb-3">
|
||||||
|
<span class="text-xs font-mono px-2 py-0.5 rounded bg-orange-500/20 text-orange-300">v1.7.40-alpha</span>
|
||||||
|
<span class="text-xs text-white/40">Apr 22, 2026</span>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||||
|
<p>Proper fix for the 500 / Internal Server Error after update. The v1.7.38 and v1.7.39 frontend archives had the wrong permissions baked into the archive itself — the tarball's root directory entry was private, so every node that extracted it ended up with a web UI directory nginx couldn't read. v1.7.40 packages the archive with correct world-readable permissions from the start, so no node ever sees the 500 again.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- v1.7.39-alpha -->
|
<!-- v1.7.39-alpha -->
|
||||||
<div>
|
<div>
|
||||||
<div class="flex items-center gap-2 mb-3">
|
<div class="flex items-center gap-2 mb-3">
|
||||||
|
|||||||
@ -87,8 +87,39 @@ if [ -z "$FRONTEND_ARCHIVE" ]; then
|
|||||||
echo " Including AIUI from demo/aiui/"
|
echo " Including AIUI from demo/aiui/"
|
||||||
cp -r "$PROJECT_ROOT/demo/aiui" "$STAGING_DIR/aiui"
|
cp -r "$PROJECT_ROOT/demo/aiui" "$STAGING_DIR/aiui"
|
||||||
fi
|
fi
|
||||||
|
# Force world-readable perms on every entry BEFORE tar, so the
|
||||||
|
# archive's internal mode bits are 755/644 regardless of what
|
||||||
|
# the staging dir's umask gave us. Without this, mktemp -d
|
||||||
|
# creates the staging dir at 700, that 700 gets baked into the
|
||||||
|
# tarball's root `./` entry, and every node that extracts the
|
||||||
|
# archive ends up with /opt/archipelago/web-ui at 700 — which
|
||||||
|
# causes nginx (www-data) to return 500 "permission denied" on
|
||||||
|
# every page. Bit us on the v1.7.38 + v1.7.39 rollouts.
|
||||||
|
chmod 755 "$STAGING_DIR"
|
||||||
|
find "$STAGING_DIR" -type d -exec chmod 755 {} +
|
||||||
|
find "$STAGING_DIR" -type f -exec chmod 644 {} +
|
||||||
echo "Creating frontend archive $FRONTEND_ARCHIVE..."
|
echo "Creating frontend archive $FRONTEND_ARCHIVE..."
|
||||||
tar -czf "$FRONTEND_ARCHIVE" -C "$STAGING_DIR" .
|
# --mode is a belt-and-braces in case a file's on-disk perms
|
||||||
|
# drift again; forces 755 dir / 644 file in the archive too.
|
||||||
|
tar --owner=0 --group=0 \
|
||||||
|
--mode='u=rwX,go=rX' \
|
||||||
|
-czf "$FRONTEND_ARCHIVE" \
|
||||||
|
-C "$STAGING_DIR" .
|
||||||
|
# Verify the archive root entry is world-readable before we
|
||||||
|
# declare success — catches regressions in tar-flag handling
|
||||||
|
# (BSD tar, busybox tar) that might silently drop --mode.
|
||||||
|
root_mode=$(tar tvzf "$FRONTEND_ARCHIVE" | head -1 | awk '{print $1}')
|
||||||
|
case "$root_mode" in
|
||||||
|
drwxr-xr-x|drwxr-x*x*)
|
||||||
|
echo " Tarball root perms OK: $root_mode"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo " ERROR: tarball root perms are $root_mode (want drwxr-xr-x) — aborting release"
|
||||||
|
rm -f "$FRONTEND_ARCHIVE"
|
||||||
|
rm -rf "$STAGING_DIR"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
rm -rf "$STAGING_DIR"
|
rm -rf "$STAGING_DIR"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user