fix(install): ship app manifests where the backend loads them + self-heal existing nodes
Fresh ISO installs had ZERO disk manifests: auto-install.sh copied apps/ to /etc/archipelago/apps but the backend/orchestrator loads /opt/archipelago/apps — so any app not overlaid by the signed catalog (netbird: 'manifests not available on this node') could never install. - installer now also populates /mnt/target/opt/archipelago/apps - bootstrap gains run_apps_dir_repair(): when /opt/archipelago/apps is empty and the installer copy exists, populate it at startup — heals already-deployed ISO nodes via OTA without reinstalling - bootstrap's bitcoin.conf repair now also ensures rpcbind=0.0.0.0 (same fix as install.rs; duplicate rpcbind with a manifest command line is harmless — bitcoind binds the first and logs the rest) Verified live on the framework node: /opt populated (56 dirs), backend restart loaded '50 app manifest(s) (disk + registry catalog)', all containers kept running (they live in user.slice, not the service cgroup). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
f2a94548ab
commit
c014c4b3ee
@ -130,6 +130,11 @@ pub async fn ensure_doctor_installed() {
|
||||
Ok(false) => debug!("Bitcoin RPC bind settings already usable"),
|
||||
Err(e) => warn!("Bitcoin RPC repair failed (non-fatal): {:#}", e),
|
||||
}
|
||||
match run_apps_dir_repair().await {
|
||||
Ok(true) => info!("Populated /opt/archipelago/apps from installer copy at /etc/archipelago/apps"),
|
||||
Ok(false) => debug!("/opt/archipelago/apps already populated (or no installer copy)"),
|
||||
Err(e) => warn!("Apps dir repair failed (non-fatal): {:#}", e),
|
||||
}
|
||||
match run_journald_dropin().await {
|
||||
Ok(true) => info!("Installed journald log-volume policy drop-in"),
|
||||
Ok(false) => debug!("journald log-volume policy already in place"),
|
||||
@ -402,6 +407,39 @@ fn path_dot(path: &Path) -> String {
|
||||
p.to_string_lossy().to_string()
|
||||
}
|
||||
|
||||
/// ISO installs before the auto-install.sh path fix copied the app manifests
|
||||
/// to /etc/archipelago/apps while the backend loads them from
|
||||
/// /opt/archipelago/apps — so fresh nodes had ZERO disk manifests and only
|
||||
/// catalog-covered apps could install (netbird "manifests not available",
|
||||
/// framework node 2026-07-14). Self-heal: when /opt has no manifests and the
|
||||
/// installer copy exists, populate /opt from /etc. Never overwrites existing
|
||||
/// /opt manifests (OTA runtime-assets sync owns those afterwards).
|
||||
async fn run_apps_dir_repair() -> Result<bool> {
|
||||
let script = r#"
|
||||
set -eu
|
||||
src=/etc/archipelago/apps
|
||||
dst=/opt/archipelago/apps
|
||||
[ -d "$src" ] || exit 0
|
||||
# Only heal when the destination has no manifests at all.
|
||||
if [ -d "$dst" ] && [ -n "$(ls -A "$dst" 2>/dev/null)" ]; then exit 0; fi
|
||||
ls "$src"/*/manifest.yml >/dev/null 2>&1 || exit 0
|
||||
mkdir -p "$dst"
|
||||
cp -r "$src"/. "$dst"/
|
||||
exit 2
|
||||
"#;
|
||||
let status = host_sudo(&["sh", "-lc", script])
|
||||
.await
|
||||
.context("populate /opt/archipelago/apps from installer copy")?;
|
||||
match status.code() {
|
||||
Some(0) => Ok(false),
|
||||
Some(2) => Ok(true),
|
||||
_ => {
|
||||
warn!("Apps dir repair helper exited with {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_bitcoin_rpc_repair() -> Result<bool> {
|
||||
// Older installs can have a container-owned bitcoin.conf with only rpcauth
|
||||
// and printtoconsole. Repair it at startup so OTA fixes existing nodes
|
||||
@ -421,6 +459,12 @@ ensure_line() {
|
||||
fi
|
||||
}
|
||||
ensure_line server=1
|
||||
# rpcbind=0.0.0.0 is required inside the container: with rpcallowip set but
|
||||
# no rpcbind, bitcoind binds RPC to the container's loopback only and every
|
||||
# dial over the container network (LND, bitcoin-ui) is refused — the fresh-
|
||||
# install "LND took 5 attempts" / bitcoin-rpc 502 failure (host publish stays
|
||||
# 127.0.0.1-only, so exposure is unchanged).
|
||||
ensure_line rpcbind=0.0.0.0
|
||||
ensure_line rpcallowip=0.0.0.0/0
|
||||
ensure_line listen=1
|
||||
# Log-volume fix: printtoconsole=1 duplicated every log line (incl. per-block
|
||||
|
||||
@ -2482,6 +2482,12 @@ fi
|
||||
|
||||
if [ -d "$BOOT_MEDIA/archipelago/apps" ]; then
|
||||
cp -r "$BOOT_MEDIA/archipelago/apps" /mnt/target/etc/archipelago/
|
||||
# The backend loads disk manifests from /opt/archipelago/apps — copying
|
||||
# only to /etc/archipelago/apps left fresh installs with ZERO manifests,
|
||||
# so any app not covered by the signed catalog (e.g. netbird) could not
|
||||
# install at all. Ship them where the orchestrator actually looks.
|
||||
mkdir -p /mnt/target/opt/archipelago/apps
|
||||
cp -r "$BOOT_MEDIA/archipelago/apps/." /mnt/target/opt/archipelago/apps/
|
||||
fi
|
||||
|
||||
# Copy pre-bundled container images
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user