Enhance ISO build process and documentation for Archipelago

- Updated BUILD-GUIDE.md to clarify instructions for building the Archipelago Auto-Installer ISO, emphasizing the recommended method of building directly on the target server.
- Added auto-installation of missing dependencies (xorriso, podman) when running the build script with sudo.
- Enhanced the build-auto-installer-iso.sh script to capture container images from the live server, ensuring the ISO includes the same set of applications as the dev server.
- Revised deployment documentation to stress the importance of building the Rust backend on the Linux dev server and included new instructions for capturing system-level changes for ISO builds.
- Improved UI components and added new bundled applications (BTCPay Server, Mempool Explorer, Nostr Relay, Strfry Relay, Tailscale) to enhance user experience.
This commit is contained in:
Dorian
2026-02-14 16:44:20 +00:00
parent d988396111
commit 6035c93289
19 changed files with 824 additions and 406 deletions
+187 -12
View File
@@ -49,6 +49,12 @@ echo ""
# Check for required tools
check_tools() {
local missing=""
local can_install=false
# Check if we can auto-install (running as root on Debian/Ubuntu)
if [ "$EUID" -eq 0 ] && [ -f /etc/debian_version ]; then
can_install=true
fi
# Check for docker or podman
if command -v docker >/dev/null 2>&1; then
@@ -65,7 +71,36 @@ check_tools() {
if [ -n "$missing" ]; then
echo "❌ Missing required tools:$missing"
echo " Install with: apt install docker.io xorriso (or podman)"
if [ "$can_install" = true ]; then
echo " 📦 Auto-installing missing dependencies..."
apt-get update -qq
if [[ "$missing" == *"xorriso"* ]]; then
apt-get install -y xorriso
fi
if [[ "$missing" == *"docker-or-podman"* ]]; then
echo " Installing podman..."
apt-get install -y podman
CONTAINER_CMD="podman"
fi
echo " ✅ Dependencies installed successfully!"
else
echo " Install with: sudo apt install xorriso podman"
echo " Or run this script with sudo to auto-install"
exit 1
fi
fi
# Re-check after potential installation
if command -v docker >/dev/null 2>&1; then
CONTAINER_CMD="docker"
elif command -v podman >/dev/null 2>&1; then
CONTAINER_CMD="podman"
else
echo "❌ Container runtime still not available after installation"
exit 1
fi
@@ -233,11 +268,66 @@ echo "📦 Step 2: Creating installer environment..."
# Download Debian Live as our installer base
BASE_ISO="$WORK_DIR/debian-live-installer.iso"
if [ ! -f "$BASE_ISO" ] || [ $(stat -f%z "$BASE_ISO" 2>/dev/null || echo 0) -lt 100000000 ]; then
echo " Downloading Debian Live base..."
rm -f "$BASE_ISO"
curl -L -o "$BASE_ISO" \
"https://sourceforge.net/projects/debian-live-respin-iso/files/standard/live-image-debian12.11-standard-20250522-amd64.hybrid.iso/download"
EXPECTED_SIZE=369000000 # ~352MB
# Check if file exists and is complete
if [ -f "$BASE_ISO" ]; then
CURRENT_SIZE=$(stat -f%z "$BASE_ISO" 2>/dev/null || stat -c%s "$BASE_ISO" 2>/dev/null || echo 0)
if [ "$CURRENT_SIZE" -ge "$EXPECTED_SIZE" ]; then
echo " ✅ Debian Live base already downloaded"
else
echo " Found incomplete download ($(($CURRENT_SIZE / 1024 / 1024))MB), removing..."
rm -f "$BASE_ISO"
fi
fi
if [ ! -f "$BASE_ISO" ]; then
echo " Downloading Debian Live base (352MB)..."
echo " (This may take 5-10 minutes depending on network speed)"
# Use wget without -O so --continue actually works
# Download with the ugly SourceForge filename, then rename
ISO_URL="https://sourceforge.net/projects/debian-live-respin-iso/files/standard/live-image-debian12.11-standard-20250522-amd64.hybrid.iso/download"
if command -v wget >/dev/null 2>&1; then
cd "$WORK_DIR"
wget --tries=10 --read-timeout=120 --continue --progress=bar:force \
--no-check-certificate \
"$ISO_URL" || {
echo " ❌ Download failed or incomplete"
echo " Partial file kept - run script again to continue"
exit 1
}
# Find the downloaded file (wget creates it with a name like "download" or the actual filename)
if [ -f "download" ]; then
mv "download" "$BASE_ISO"
elif [ -f "live-image-debian12.11-standard-20250522-amd64.hybrid.iso" ]; then
mv "live-image-debian12.11-standard-20250522-amd64.hybrid.iso" "$BASE_ISO"
else
echo " ❌ Downloaded file not found"
exit 1
fi
else
# Fallback to curl (no resume support)
curl -L --location-trusted --retry 10 --retry-delay 5 \
--connect-timeout 60 --max-time 1800 \
-o "$BASE_ISO" \
"$ISO_URL" || {
echo " ❌ Download failed"
rm -f "$BASE_ISO"
exit 1
}
fi
# Verify download size
FINAL_SIZE=$(stat -f%z "$BASE_ISO" 2>/dev/null || stat -c%s "$BASE_ISO" 2>/dev/null || echo 0)
if [ "$FINAL_SIZE" -lt "$EXPECTED_SIZE" ]; then
echo " ❌ Download incomplete: got $(($FINAL_SIZE / 1024 / 1024))MB, expected 352MB"
exit 1
fi
echo " ✅ Download complete ($(($FINAL_SIZE / 1024 / 1024))MB)"
fi
echo " Extracting installer base..."
@@ -386,14 +476,41 @@ echo "📦 Step 3b: Bundling container images for offline use..."
IMAGES_DIR="$ARCH_DIR/container-images"
mkdir -p "$IMAGES_DIR"
# Define images to bundle (space-separated: image filename)
# When DEV_SERVER is set (and not localhost), try to capture images from live server
# so the ISO includes the same set as the dev server (including custom UIs: bitcoin-ui, lnd-ui).
IMAGES_CAPTURED_FROM_SERVER=0
if [ -n "$DEV_SERVER" ] && [ "$DEV_SERVER" != "localhost" ] && [ "$DEV_SERVER" != "127.0.0.1" ]; then
echo " Capturing container images from live server ($DEV_SERVER)..."
CAPTURE_PATTERNS="bitcoin-ui bitcoin-knots lnd lnd-ui filebrowser mempool tailscale homeassistant btcpayserver nostr-rs-relay strfry"
REMOTE_TMP="/tmp/archipelago-image-capture-$$"
SAVED_LIST=$(ssh "$DEV_SERVER" "mkdir -p $REMOTE_TMP && for p in $CAPTURE_PATTERNS; do img=\$(sudo podman images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null | grep -i \"\$p\" | head -1); [ -n \"\$img\" ] && sudo podman save -o \"$REMOTE_TMP/\$p.tar\" \"\$img\" 2>/dev/null && echo \"\$p\"; done" 2>/dev/null) || true
for p in $SAVED_LIST; do
if [ -n "$p" ] && scp "$DEV_SERVER:$REMOTE_TMP/$p.tar" "$IMAGES_DIR/$p.tar" 2>/dev/null; then
echo " ✅ Captured from server: $p.tar"
IMAGES_CAPTURED_FROM_SERVER=1
fi
done
ssh "$DEV_SERVER" "rm -rf $REMOTE_TMP" 2>/dev/null || true
if [ "$IMAGES_CAPTURED_FROM_SERVER" = "0" ]; then
echo " ⚠️ No images captured from server, will use registry pull fallback"
fi
fi
# Define images to bundle for fallback (when not from server or missing). Includes filebrowser.
# bitcoin-ui and lnd-ui are custom and normally captured from server or built separately.
CONTAINER_IMAGES="
bitcoinknots/bitcoin:29 bitcoin-knots.tar
lightninglabs/lnd:v0.18.4-beta lnd.tar
ghcr.io/home-assistant/home-assistant:stable homeassistant.tar
btcpayserver/btcpayserver:latest btcpayserver.tar
mempool/frontend:latest mempool.tar
docker.io/filebrowser/filebrowser:latest filebrowser.tar
scsibug/nostr-rs-relay:latest nostr-rs-relay.tar
hoytech/strfry:latest strfry.tar
tailscale/tailscale:latest tailscale.tar
"
# Pull and save each image (force AMD64 for x86_64 target)
# Pull and save each image (force AMD64 for x86_64 target) only if not already present
echo "$CONTAINER_IMAGES" | while read -r image filename; do
[ -z "$image" ] && continue
tarpath="$IMAGES_DIR/$filename"
@@ -711,9 +828,36 @@ if [ -t 0 ] && [ -z "$ARCHIPELAGO_WELCOMED" ]; then
export ARCHIPELAGO_WELCOMED=1
IP=$(hostname -I 2>/dev/null | awk '{print $1}')
echo ""
echo " ╔═══════════════════════════════════════════════════════════╗"
echo " 🏝️ ARCHIPELAGO BITCOIN NODE OS "
echo " ╚═══════════════════════════════════════════════════════════╝"
echo " _"
echo " ,--.\\\`-. __"
echo " _,.\\\`. \\:/,\" \\\`-._"
echo " ,-*\" _,.-;-*\\\`-.+\"*._ )"
echo " ( ,.\"* ,-\" / \\\`. \\\\. \\\`."
echo " ,\" ,;\" ,\"\\../\\ \\: \\"
echo " ( ,\"/ / \\\\.,' : )) /"
echo " \\ |/ / \\\\.,' / // ,'"
echo " \\_)\\ ,' \\\\.,' ( / )/"
echo " \\\` \\._,' \\\`\""
echo " \\..\/"
echo " \\..\/"
echo " ~ ~\\..\/ ~~ ~~"
echo " ~~ ~~ \\..\/ ~~ ~ ~~"
echo " ~~ ~ ~~ __...---\\../-...__ ~~~ ~~"
echo " ~~~~ ~_,--' \\..\/ \\\`--.__ ~~ ~~"
echo " ~~~ __,--' \\\`\" \\\`--.__ ~~~"
echo "~~ ,--' \\\`--."
echo " '------......______ ______......------\\\` ~~"
echo " ~~~ ~ ~~ ~ \\\`\\\`\\\`\\\`\\\`---\"\"\"\"\" ~~ ~ ~~"
echo " ~~~~ ~~ ~~~~ ~~~~~~ ~ ~~ ~~ ~~~ ~"
echo ""
echo " █████╗ ██████╗ ██████╗██╗ ██╗██╗██████╗ ███████╗██╗ █████╗ ██████╗ ██████╗ "
echo " ██╔══██╗██╔══██╗██╔════╝██║ ██║██║██╔══██╗██╔════╝██║ ██╔══██╗██╔════╝ ██╔═══██╗"
echo " ███████║██████╔╝██║ ███████║██║██████╔╝█████╗ ██║ ███████║██║ ███╗██║ ██║"
echo " ██╔══██║██╔══██╗██║ ██╔══██║██║██╔═══╝ ██╔══╝ ██║ ██╔══██║██║ ██║██║ ██║"
echo " ██║ ██║██║ ██║╚██████╗██║ ██║██║██║ ███████╗███████╗██║ ██║╚██████╔╝╚██████╔╝"
echo " ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ "
echo ""
echo " 🏝️ BITCOIN NODE OS 🏝️"
echo ""
if [ -n "$IP" ]; then
echo " 🌐 Web UI: http://$IP"
@@ -774,9 +918,39 @@ umount /mnt/target/dev 2>/dev/null || true
umount /mnt/target/boot/efi 2>/dev/null || true
umount /mnt/target 2>/dev/null || true
echo ""
echo -e "${GREEN} _${NC}"
echo -e "${GREEN} ,--.\\\`-. __${NC}"
echo -e "${GREEN} _,.\\\`. \\:/,\" \\\`-._${NC}"
echo -e "${GREEN} ,-*\" _,.-;-*\\\`-.+\"*._ )${NC}"
echo -e "${GREEN} ( ,.\"* ,-\" / \\\`. \\\\. \\\`.${NC}"
echo -e "${GREEN} ,\" ,;\" ,\"\\../\\ \\: \\${NC}"
echo -e "${GREEN} ( ,\"/ / \\\\.,' : )) /${NC}"
echo -e "${GREEN} \\ |/ / \\\\.,' / // ,'${NC}"
echo -e "${GREEN} \\_)\\ ,' \\\\.,' ( / )/${NC}"
echo -e "${GREEN} \\\` \\._,' \\\`\"${NC}"
echo -e "${GREEN} \\../${NC}"
echo -e "${GREEN} \\../${NC}"
echo -e "${GREEN} ~ ~\\../ ~~ ~~${NC}"
echo -e "${GREEN} ~~ ~~ \\../ ~~ ~ ~~${NC}"
echo -e "${GREEN} ~~ ~ ~~ __...---\\../-...__ ~~~ ~~${NC}"
echo -e "${GREEN} ~~~~ ~_,--' \\../ \\\`--.__ ~~ ~~${NC}"
echo -e "${GREEN} ~~~ __,--' \\\`\" \\\`--.__ ~~~${NC}"
echo -e "${GREEN}~~ ,--' \\\`--.${NC}"
echo -e "${GREEN} '------......______ ______......------\\\` ~~${NC}"
echo -e "${GREEN} ~~~ ~ ~~ ~ \\\`\\\`\\\`\\\`\\\`---\"\"\"\"\" ~~ ~ ~~${NC}"
echo -e "${GREEN} ~~~~ ~~ ~~~~ ~~~~~~ ~ ~~ ~~ ~~~ ~${NC}"
echo ""
echo -e "${GREEN} █████╗ ██████╗ ██████╗██╗ ██╗██╗██████╗ ███████╗██╗ █████╗ ██████╗ ██████╗ ${NC}"
echo -e "${GREEN} ██╔══██╗██╔══██╗██╔════╝██║ ██║██║██╔══██╗██╔════╝██║ ██╔══██╗██╔════╝ ██╔═══██╗${NC}"
echo -e "${GREEN} ███████║██████╔╝██║ ███████║██║██████╔╝█████╗ ██║ ███████║██║ ███╗██║ ██║${NC}"
echo -e "${GREEN} ██╔══██║██╔══██╗██║ ██╔══██║██║██╔═══╝ ██╔══╝ ██║ ██╔══██║██║ ██║██║ ██║${NC}"
echo -e "${GREEN} ██║ ██║██║ ██║╚██████╗██║ ██║██║██║ ███████╗███████╗██║ ██║╚██████╔╝╚██████╔╝${NC}"
echo -e "${GREEN} ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ${NC}"
echo ""
echo -e "${GREEN} 🏝️ BITCOIN NODE OS 🏝️${NC}"
echo ""
echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║ ✅ INSTALLATION COMPLETE! ║${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║ Remove the USB drive and press Enter to reboot. ║${NC}"
@@ -789,6 +963,7 @@ echo -e "${GREEN}║ • Web Password: password123
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║ Pre-loaded apps (ready to start via Web UI): ║${NC}"
echo -e "${GREEN}║ • Bitcoin Knots • LND • Home Assistant ║${NC}"
echo -e "${GREEN}║ • BTCPay Server • Mempool • Nostr Relays ║${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════════╝${NC}"
echo ""