feat(self-update): sync and rebuild UI containers on OTA
self-update.sh previously rebuilt only the backend binary and Vue
frontend. The custom UI containers (archy-bitcoin-ui, archy-lnd-ui,
archy-electrs-ui) were left untouched forever. That meant any change to
docker/<ui>/{Dockerfile, nginx.conf, index.html, ...} never reached a
running node through OTA; it required a manual SSH + rebuild. This is
exactly why the lnd-ui port fix didnt reach .228 in v1.7.43-alpha.
Add a sync-and-rebuild stage:
1. Hash each docker/<ui>/ tree (content-only, path-stable via
`cd && find` so src and dst compare equal when identical).
2. rsync changed trees to /opt/archipelago/docker/<ui>/.
3. For each changed UI: rebuild image as the archipelago user
(rootless podman), then stop+remove+recreate the container using
the canonical spec from scripts/container-specs.sh. Port mappings,
caps, memory, and security opts all come from the spec, so the
runtime cant drift from the tree.
Also install first-boot-containers.sh into /opt/archipelago/scripts/ so
a later reconciler run or reboot picks up current orchestration logic.
Idempotent: if no UI tree changed since the last update, the whole stage
is a no-op beyond the hash compare. Verified end-to-end on .228 with a
synthetic change to lnd-ui: detection, sync, build, recreate, and HTTP
200 on both the direct container port and the host-nginx /app/lnd/
proxy.
This commit is contained in:
parent
72dec5aaa5
commit
ce39430b33
@ -200,6 +200,96 @@ if [ -f "$REPO_DIR/scripts/image-versions.sh" ]; then
|
|||||||
sudo cp "$REPO_DIR/scripts/image-versions.sh" /opt/archipelago/image-versions.sh
|
sudo cp "$REPO_DIR/scripts/image-versions.sh" /opt/archipelago/image-versions.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Update first-boot-containers.sh too (the canonical first-boot orchestrator).
|
||||||
|
# Nodes run it once on install, but keeping a fresh copy on disk means any
|
||||||
|
# future boot or reconciler invocation uses current port specs and caps.
|
||||||
|
if [ -f "$REPO_DIR/scripts/first-boot-containers.sh" ]; then
|
||||||
|
sudo install -m 755 "$REPO_DIR/scripts/first-boot-containers.sh" \
|
||||||
|
"$SCRIPTS_DEST/first-boot-containers.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync UI container source trees (docker/bitcoin-ui, docker/lnd-ui,
|
||||||
|
# docker/electrs-ui) into /opt/archipelago/docker/<name>/. If any file in a
|
||||||
|
# UI tree changed since last update, rebuild that image and recreate its
|
||||||
|
# container using the spec from container-specs.sh. This is what prevented
|
||||||
|
# the lnd-ui port mismatch from reaching nodes through OTA: self-update used
|
||||||
|
# to update only the backend + frontend, never the UI container images.
|
||||||
|
UI_DOCKER_DEST="/opt/archipelago/docker"
|
||||||
|
sudo mkdir -p "$UI_DOCKER_DEST"
|
||||||
|
UI_REBUILD_LIST=""
|
||||||
|
for ui in bitcoin-ui lnd-ui electrs-ui; do
|
||||||
|
src="$REPO_DIR/docker/$ui"
|
||||||
|
dst="$UI_DOCKER_DEST/$ui"
|
||||||
|
[ -d "$src" ] || continue
|
||||||
|
# Hash source tree to decide if rebuild is needed. Any content change
|
||||||
|
# (Dockerfile, nginx.conf, index.html, assets) triggers a rebuild.
|
||||||
|
# Hash file contents only (not paths or metadata) so src and dst match
|
||||||
|
# when their contents are identical regardless of directory prefix.
|
||||||
|
src_hash=$( (cd "$src" && find . -type f | LC_ALL=C sort | xargs sha256sum 2>/dev/null) | sha256sum | cut -d' ' -f1)
|
||||||
|
dst_hash=""
|
||||||
|
if [ -d "$dst" ]; then
|
||||||
|
dst_hash=$( (cd "$dst" && find . -type f | LC_ALL=C sort | xargs sha256sum 2>/dev/null) | sha256sum | cut -d' ' -f1)
|
||||||
|
fi
|
||||||
|
if [ "$src_hash" != "$dst_hash" ]; then
|
||||||
|
log "UI source changed for $ui; syncing and marking for rebuild"
|
||||||
|
sudo rsync -a --delete "$src/" "$dst/"
|
||||||
|
UI_REBUILD_LIST="$UI_REBUILD_LIST $ui"
|
||||||
|
else
|
||||||
|
ok "UI source unchanged for $ui"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Rebuild changed UI images + recreate containers as the archipelago user
|
||||||
|
# (rootless podman storage lives under ~archipelago). Port mappings and caps
|
||||||
|
# come from scripts/container-specs.sh so spec drift can't sneak in.
|
||||||
|
if [ -n "$UI_REBUILD_LIST" ]; then
|
||||||
|
log "Rebuilding UI containers:$UI_REBUILD_LIST"
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
# container-specs.sh provides load_spec_archy-<ui> and mem_limit <name>.
|
||||||
|
SPECS="$SCRIPTS_DEST/container-specs.sh"
|
||||||
|
if [ ! -f "$SPECS" ]; then
|
||||||
|
warn "container-specs.sh missing at $SPECS; skipping UI rebuild"
|
||||||
|
else
|
||||||
|
for ui in $UI_REBUILD_LIST; do
|
||||||
|
cname="archy-$ui"
|
||||||
|
log " rebuilding $cname from $UI_DOCKER_DEST/$ui"
|
||||||
|
# Build image as archipelago user so it lands in the right store.
|
||||||
|
if ! sudo -u archipelago bash -c "
|
||||||
|
export XDG_RUNTIME_DIR=/run/user/\$(id -u archipelago)
|
||||||
|
cd '$UI_DOCKER_DEST/$ui' &&
|
||||||
|
podman build --no-cache -t 'localhost/$ui:local' . >>'$LOG_FILE' 2>&1
|
||||||
|
"; then
|
||||||
|
err " build failed for $ui; keeping existing container"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Recreate container using spec from container-specs.sh.
|
||||||
|
if ! sudo -u archipelago bash -c "
|
||||||
|
export XDG_RUNTIME_DIR=/run/user/\$(id -u archipelago)
|
||||||
|
source '$SPECS'
|
||||||
|
load_spec_$cname || { echo 'spec load failed for $cname'; exit 1; }
|
||||||
|
podman stop '$cname' 2>/dev/null || true
|
||||||
|
podman rm '$cname' 2>/dev/null || true
|
||||||
|
PORT_ARG=''
|
||||||
|
[ -n \"\$SPEC_PORTS\" ] && PORT_ARG=\"-p \$SPEC_PORTS\"
|
||||||
|
NET_ARG=''
|
||||||
|
[ \"\$SPEC_NETWORK\" = 'host' ] && NET_ARG='--network host'
|
||||||
|
CAP_ARGS='--cap-drop ALL'
|
||||||
|
for c in \$SPEC_CAPS; do CAP_ARGS=\"\$CAP_ARGS --cap-add \$c\"; done
|
||||||
|
podman run -d --name '$cname' \$PORT_ARG \$NET_ARG \\
|
||||||
|
--user 0:0 \$CAP_ARGS \\
|
||||||
|
--memory=\"\$SPEC_MEMORY\" \\
|
||||||
|
--restart unless-stopped \\
|
||||||
|
--security-opt \"\$SPEC_SECURITY\" \\
|
||||||
|
'localhost/$ui:local' >>'$LOG_FILE' 2>&1
|
||||||
|
"; then
|
||||||
|
err " recreate failed for $cname"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
ok " $cname rebuilt and running"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Update systemd service if changed
|
# Update systemd service if changed
|
||||||
if [ -f "$REPO_DIR/image-recipe/configs/archipelago.service" ]; then
|
if [ -f "$REPO_DIR/image-recipe/configs/archipelago.service" ]; then
|
||||||
if ! diff -q "$REPO_DIR/image-recipe/configs/archipelago.service" /etc/systemd/system/archipelago.service &>/dev/null; then
|
if ! diff -q "$REPO_DIR/image-recipe/configs/archipelago.service" /etc/systemd/system/archipelago.service &>/dev/null; then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user