diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e3c8697..b2e7bec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.7.53-alpha (2026-05-05) + +- Bitcoin Knots/Core config generation no longer duplicates RPC bind and port settings between `bitcoin.conf` and container command args, fixing `Unable to bind all endpoints for RPC server` startup failures. +- Legacy Bitcoin container healthchecks no longer depend on `bitcoin-cli`, which is absent from current Knots images and can wedge Podman healthcheck runners. +- Update checks now prefer manifest OTA releases over stale git remotes unless `ARCHIPELAGO_GIT_UPDATES` is explicitly enabled, so installed nodes can see published releases from the VPS mirror. + ## v1.7.52-alpha (2026-05-05) - Tailscale now launches the local installed web UI on port `8240` and starts `tailscaled` before `tailscale web`, fixing unreachable installs after container creation. diff --git a/core/Cargo.lock b/core/Cargo.lock index 6900f6e3..44c2c4a6 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "archipelago" -version = "1.7.52-alpha" +version = "1.7.53-alpha" dependencies = [ "anyhow", "archipelago-container", diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index 4315f3f9..5972d920 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "archipelago" -version = "1.7.52-alpha" +version = "1.7.53-alpha" edition = "2021" description = "Archipelago Bitcoin Node OS - Native backend" authors = ["Archipelago Team"] diff --git a/core/archipelago/src/api/rpc/package/config.rs b/core/archipelago/src/api/rpc/package/config.rs index b1b80218..286dd676 100644 --- a/core/archipelago/src/api/rpc/package/config.rs +++ b/core/archipelago/src/api/rpc/package/config.rs @@ -164,11 +164,10 @@ pub(super) fn is_readonly_compatible(app_id: &str) -> bool { /// Get container health check arguments for podman run. /// Returns (health-cmd, interval, retries) args to append to run_args. pub(super) fn get_health_check_args(app_id: &str, _rpc_pass: &str) -> Vec { - // bitcoin-cli reads the .cookie file from -datadir automatically (no plaintext creds needed) - let btc_health = - "bitcoin-cli -datadir=/home/bitcoin/.bitcoin getblockchaininfo || exit 1".to_string(); let (cmd, interval, retries) = match app_id { - "bitcoin" | "bitcoin-core" | "bitcoin-knots" => (btc_health.as_str(), "30s", "3"), + // Bitcoin images do not consistently ship bitcoin-cli/curl/nc. Rely on + // process state here; manifests still describe the desired TCP check. + "bitcoin" | "bitcoin-core" | "bitcoin-knots" => return vec![], "lnd" => ("lncli getinfo || exit 1", "30s", "3"), "btcpay-server" | "btcpayserver" => { ("curl -sf http://localhost:49392/ || exit 1", "30s", "3") diff --git a/core/archipelago/src/api/rpc/package/install.rs b/core/archipelago/src/api/rpc/package/install.rs index 379bdc75..cfffe7a9 100644 --- a/core/archipelago/src/api/rpc/package/install.rs +++ b/core/archipelago/src/api/rpc/package/install.rs @@ -260,7 +260,7 @@ impl RpcHandler { // bitcoin_rpc_credentials() generates + persists on first // call (OnceCell-cached), so this is idempotent. let _ = crate::bitcoin_rpc::bitcoin_rpc_credentials().await; - ensure_bitcoin_rpc_bindings().await? + ensure_bitcoin_rpc_config().await? } else { false }; @@ -1175,14 +1175,14 @@ impl RpcHandler { // user" and skip. Matches the lnd.conf behavior below. match tokio::fs::metadata(&conf_path).await { Ok(_) => { - ensure_bitcoin_rpc_bindings().await?; - info!("bitcoin.conf already exists, ensured RPC bind settings"); + ensure_bitcoin_rpc_config().await?; + info!("bitcoin.conf already exists, ensured Bitcoin RPC config"); return Ok(()); } Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} Err(_) => { - ensure_bitcoin_rpc_bindings().await?; - info!("bitcoin.conf path inaccessible, ensured RPC bind settings via host helper"); + ensure_bitcoin_rpc_config().await?; + info!("bitcoin.conf path inaccessible, ensured Bitcoin RPC config via host helper"); return Ok(()); } } @@ -1205,9 +1205,7 @@ impl RpcHandler { # rpcauth: salted hash only — no plaintext password in config or CLI\n\ {}\n\ server=1\n\ -rpcbind=0.0.0.0\n\ rpcallowip=0.0.0.0/0\n\ -rpcport=8332\n\ listen=1\n\ printtoconsole=1\n", rpcauth_line @@ -2029,7 +2027,7 @@ async fn wait_for_adopted_container(package_id: &str, container_name: &str) -> R )) } -async fn ensure_bitcoin_rpc_bindings() -> Result { +async fn ensure_bitcoin_rpc_config() -> Result { let script = r#" set -eu conf=/var/lib/archipelago/bitcoin/bitcoin.conf @@ -2044,9 +2042,7 @@ ensure_line() { fi } ensure_line server=1 -ensure_line rpcbind=0.0.0.0 ensure_line rpcallowip=0.0.0.0/0 -ensure_line rpcport=8332 ensure_line listen=1 [ "$changed" -eq 0 ] && exit 0 exit 2 diff --git a/core/archipelago/src/api/rpc/update.rs b/core/archipelago/src/api/rpc/update.rs index b0935f69..fc95ae02 100644 --- a/core/archipelago/src/api/rpc/update.rs +++ b/core/archipelago/src/api/rpc/update.rs @@ -4,26 +4,9 @@ use anyhow::{Context, Result}; impl RpcHandler { /// Check for available system updates. - /// Tries git-based check first (if repo exists), falls back to manifest-based. + /// Prefer manifest-based OTA so installed nodes with a checked-out repo do + /// not depend on a potentially stale git remote. Git remains a dev fallback. pub(super) async fn handle_update_check(&self) -> Result { - // Manifest override: when ARCHIPELAGO_UPDATE_URL is explicitly set, - // the operator wants OTA via manifest — typically a dev box where - // ~/archy/.git exists but isn't the intended update surface. - // Without this short-circuit the dev box always advertises "Pull - // & Rebuild" and can never exercise the manifest OTA path. - let manifest_override = std::env::var("ARCHIPELAGO_UPDATE_URL").is_ok(); - - let repo_dir = std::path::PathBuf::from( - std::env::var("HOME").unwrap_or_else(|_| "/home/archipelago".to_string()), - ) - .join("archy"); - if !manifest_override && repo_dir.join(".git").exists() { - if let Ok(git_status) = self.git_check_update(&repo_dir).await { - return Ok(git_status); - } - } - - // Fall back to manifest-based check let state = update::check_for_updates(&self.config.data_dir).await?; let update_info = state.available_update.as_ref().map(|u| { @@ -35,10 +18,30 @@ impl RpcHandler { }) }); + if update_info.is_some() { + return Ok(serde_json::json!({ + "current_version": state.current_version, + "last_check": state.last_check, + "update_available": true, + "update": update_info, + "manifest_mirror": state.manifest_mirror, + })); + } + + let repo_dir = std::path::PathBuf::from( + std::env::var("HOME").unwrap_or_else(|_| "/home/archipelago".to_string()), + ) + .join("archy"); + if std::env::var("ARCHIPELAGO_GIT_UPDATES").is_ok() && repo_dir.join(".git").exists() { + if let Ok(git_status) = self.git_check_update(&repo_dir).await { + return Ok(git_status); + } + } + Ok(serde_json::json!({ "current_version": state.current_version, "last_check": state.last_check, - "update_available": update_info.is_some(), + "update_available": false, "update": update_info, "manifest_mirror": state.manifest_mirror, })) diff --git a/core/archipelago/src/bootstrap.rs b/core/archipelago/src/bootstrap.rs index 01668fcf..bf62dd16 100644 --- a/core/archipelago/src/bootstrap.rs +++ b/core/archipelago/src/bootstrap.rs @@ -304,10 +304,9 @@ fn path_dot(path: &Path) -> String { async fn run_bitcoin_rpc_repair() -> Result { // Older installs can have a container-owned bitcoin.conf with only rpcauth - // and printtoconsole. In that state bitcoind is healthy internally, but the - // host-network bitcoin-ui proxy to 127.0.0.1:8332 gets connection resets. - // Repair it at startup so OTA fixes existing nodes without a manual - // uninstall/reinstall. + // and printtoconsole. Repair it at startup so OTA fixes existing nodes + // without a manual uninstall/reinstall. Bind/port stay in the container + // command line to avoid duplicate RPC endpoint definitions. let script = r#" set -eu conf=/var/lib/archipelago/bitcoin/bitcoin.conf @@ -322,9 +321,7 @@ ensure_line() { fi } ensure_line server=1 -ensure_line rpcbind=0.0.0.0 ensure_line rpcallowip=0.0.0.0/0 -ensure_line rpcport=8332 ensure_line listen=1 [ "$changed" -eq 0 ] && exit 0 exit 2 diff --git a/image-recipe/archipelago-scripts/setup-bitcoin.sh b/image-recipe/archipelago-scripts/setup-bitcoin.sh index eea31817..e80fa10f 100755 --- a/image-recipe/archipelago-scripts/setup-bitcoin.sh +++ b/image-recipe/archipelago-scripts/setup-bitcoin.sh @@ -56,7 +56,6 @@ listen=1 # RPC rpcuser=$RPC_USER rpcpassword=$RPC_PASS -rpcbind=0.0.0.0 rpcallowip=10.0.0.0/8 rpcallowip=172.16.0.0/12 rpcallowip=192.168.0.0/16 diff --git a/neode-ui/package-lock.json b/neode-ui/package-lock.json index be273b8f..c3bab477 100644 --- a/neode-ui/package-lock.json +++ b/neode-ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "neode-ui", - "version": "1.7.52-alpha", + "version": "1.7.53-alpha", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "neode-ui", - "version": "1.7.52-alpha", + "version": "1.7.53-alpha", "dependencies": { "@types/dompurify": "^3.0.5", "@vue-leaflet/vue-leaflet": "^0.10.1", diff --git a/neode-ui/package.json b/neode-ui/package.json index 8f4addba..bade5448 100644 --- a/neode-ui/package.json +++ b/neode-ui/package.json @@ -1,7 +1,7 @@ { "name": "neode-ui", "private": true, - "version": "1.7.52-alpha", + "version": "1.7.53-alpha", "type": "module", "scripts": { "start": "./start-dev.sh", diff --git a/release-manifest.json b/release-manifest.json index 3c25e4e8..dad5d123 100644 --- a/release-manifest.json +++ b/release-manifest.json @@ -1,28 +1,27 @@ { - "version": "1.7.52-alpha", + "version": "1.7.53-alpha", "release_date": "2026-05-05", "changelog": [ - "Tailscale now launches the local installed web UI on port `8240` and starts `tailscaled` before `tailscale web`, fixing unreachable installs after container creation.", - "Grafana install/start/restart now repairs missing rootless host listeners on port `3000`, matching the existing SearXNG, Uptime Kuma, and Gitea recovery path.", - "Debian 13/Trixie ISO and disk-install paths now force security updates from `trixie-security` during image/install creation so rebuilt release media includes patched base packages.", - "Broad `.198` lifecycle audit passes with the current qualified app set; known absent blockers remain `electrumx`, `photoprism`, `dwn`, and `ollama`." + "Bitcoin Knots/Core config generation no longer duplicates RPC bind and port settings between `bitcoin.conf` and container command args, fixing `Unable to bind all endpoints for RPC server` startup failures.", + "Legacy Bitcoin container healthchecks no longer depend on `bitcoin-cli`, which is absent from current Knots images and can wedge Podman healthcheck runners.", + "Update checks now prefer manifest OTA releases over stale git remotes unless `ARCHIPELAGO_GIT_UPDATES` is explicitly enabled, so installed nodes can see published releases from the VPS mirror." ], "components": [ { "name": "archipelago", - "current_version": "1.7.52-alpha", - "new_version": "1.7.52-alpha", - "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.52-alpha/archipelago", - "sha256": "fc47c3bc42f67472252cb854bb03e200a92929ab38aeac519422704486af18d4", - "size_bytes": 42342368 + "current_version": "1.7.53-alpha", + "new_version": "1.7.53-alpha", + "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.53-alpha/archipelago", + "sha256": "86cf408ed84c7a7a72d1b5529aa97561dd02db38aab57c523999d1f5e7bf48b7", + "size_bytes": 42352112 }, { - "name": "archipelago-frontend-1.7.52-alpha.tar.gz", - "current_version": "1.7.52-alpha", - "new_version": "1.7.52-alpha", - "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.52-alpha/archipelago-frontend-1.7.52-alpha.tar.gz", - "sha256": "329e57a0491e91966afcd5a82f5c00920657695b01ecc6c9e99c6814b44abf29", - "size_bytes": 166462645 + "name": "archipelago-frontend-1.7.53-alpha.tar.gz", + "current_version": "1.7.53-alpha", + "new_version": "1.7.53-alpha", + "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.53-alpha/archipelago-frontend-1.7.53-alpha.tar.gz", + "sha256": "87590acd32cb79866d39d87f37c7a91d85774d06aa318352b24d2b2177ccac31", + "size_bytes": 166460672 } ] } diff --git a/scripts/container-doctor.sh b/scripts/container-doctor.sh index 0be90f9b..54dbc354 100755 --- a/scripts/container-doctor.sh +++ b/scripts/container-doctor.sh @@ -266,10 +266,8 @@ server=1 prune=550 rpcuser=archipelago rpcpassword=$BTC_RPC_PASS -rpcbind=0.0.0.0 rpcallowip=127.0.0.1/32 rpcallowip=10.88.0.0/16 -rpcport=8332 listen=1 printtoconsole=1 BCONF diff --git a/scripts/first-boot-containers.sh b/scripts/first-boot-containers.sh index eac73ba9..f540e7e1 100644 --- a/scripts/first-boot-containers.sh +++ b/scripts/first-boot-containers.sh @@ -308,9 +308,7 @@ if [ ! -f "$BITCOIN_CONF" ] || ! grep -q "^rpcauth=" "$BITCOIN_CONF" 2>/dev/null # rpcauth: salted hash only — no plaintext password in config or CLI rpcauth=${RPCAUTH} server=1 -rpcbind=0.0.0.0 rpcallowip=0.0.0.0/0 -rpcport=8332 listen=1 printtoconsole=1 # ZMQ publishers for LND and other services that need real-time block/tx notifications