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:
@@ -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 ""
|
||||
|
||||
Reference in New Issue
Block a user