- 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.
401 lines
13 KiB
Bash
Executable File
401 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
||
#
|
||
# Archipelago Complete ISO Build System
|
||
# =====================================
|
||
#
|
||
# This script builds a complete, flashable ISO from source with one command.
|
||
# It handles backend compilation, frontend bundling, and ISO creation.
|
||
#
|
||
# Usage:
|
||
# ./build-iso-complete.sh [options]
|
||
#
|
||
# Options:
|
||
# --local Build everything locally (requires Rust + Node.js)
|
||
# --remote HOST Build on remote server (recommended for ARM -> x86 cross-compile)
|
||
# --skip-backend Skip backend compilation (use existing binary)
|
||
# --skip-frontend Skip frontend build (use existing dist)
|
||
# --clean Clean all build artifacts before building
|
||
# --help Show this help message
|
||
#
|
||
# Examples:
|
||
# ./build-iso-complete.sh --remote archipelago@192.168.1.228
|
||
# ./build-iso-complete.sh --local --clean
|
||
#
|
||
# Auto-installer from live server: when using --remote HOST, the ISO script
|
||
# (build-auto-installer-iso.sh) is run with DEV_SERVER=HOST so it captures
|
||
# backend, frontend, and container images from that host. Alternatively run
|
||
# DEV_SERVER=archipelago@192.168.1.228 ./image-recipe/build-auto-installer-iso.sh
|
||
# to build the auto-installer ISO with live capture only (no backend/frontend build).
|
||
#
|
||
|
||
set -e # Exit on error
|
||
|
||
# =============================================================================
|
||
# Configuration
|
||
# =============================================================================
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
BUILD_DIR="$SCRIPT_DIR/image-recipe/build"
|
||
BACKEND_SRC="$SCRIPT_DIR/core/archipelago"
|
||
FRONTEND_SRC="$SCRIPT_DIR/neode-ui"
|
||
ISO_SCRIPT="$SCRIPT_DIR/image-recipe/build-auto-installer-iso.sh"
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Build options (defaults)
|
||
BUILD_MODE="remote"
|
||
REMOTE_HOST=""
|
||
SKIP_BACKEND=false
|
||
SKIP_FRONTEND=false
|
||
CLEAN_BUILD=false
|
||
|
||
# =============================================================================
|
||
# Helper Functions
|
||
# =============================================================================
|
||
|
||
print_header() {
|
||
echo ""
|
||
echo -e "${BLUE}╔════════════════════════════════════════════════════════╗${NC}"
|
||
echo -e "${BLUE}║${NC} $1"
|
||
echo -e "${BLUE}╚════════════════════════════════════════════════════════╝${NC}"
|
||
echo ""
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
show_help() {
|
||
head -n 25 "$0" | grep "^#" | sed 's/^# //' | sed 's/^#//'
|
||
exit 0
|
||
}
|
||
|
||
check_command() {
|
||
if ! command -v "$1" &> /dev/null; then
|
||
print_error "$1 is not installed"
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
# =============================================================================
|
||
# Parse Arguments
|
||
# =============================================================================
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--local)
|
||
BUILD_MODE="local"
|
||
shift
|
||
;;
|
||
--remote)
|
||
BUILD_MODE="remote"
|
||
REMOTE_HOST="$2"
|
||
shift 2
|
||
;;
|
||
--skip-backend)
|
||
SKIP_BACKEND=true
|
||
shift
|
||
;;
|
||
--skip-frontend)
|
||
SKIP_FRONTEND=true
|
||
shift
|
||
;;
|
||
--clean)
|
||
CLEAN_BUILD=true
|
||
shift
|
||
;;
|
||
--help|-h)
|
||
show_help
|
||
;;
|
||
*)
|
||
print_error "Unknown option: $1"
|
||
show_help
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# =============================================================================
|
||
# Pre-flight Checks
|
||
# =============================================================================
|
||
|
||
print_header "Archipelago Complete ISO Builder"
|
||
|
||
print_info "Build mode: $BUILD_MODE"
|
||
[[ -n "$REMOTE_HOST" ]] && print_info "Remote host: $REMOTE_HOST"
|
||
[[ "$SKIP_BACKEND" = true ]] && print_warning "Skipping backend build"
|
||
[[ "$SKIP_FRONTEND" = true ]] && print_warning "Skipping frontend build"
|
||
[[ "$CLEAN_BUILD" = true ]] && print_warning "Clean build enabled"
|
||
|
||
echo ""
|
||
|
||
# Check for required commands
|
||
if [[ "$BUILD_MODE" == "remote" ]] && [[ -z "$REMOTE_HOST" ]]; then
|
||
print_error "Remote build mode requires --remote HOST"
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "$BUILD_MODE" == "remote" ]]; then
|
||
if ! check_command ssh; then
|
||
exit 1
|
||
fi
|
||
if ! check_command rsync; then
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Step 1: Clean Build Artifacts (if requested)
|
||
# =============================================================================
|
||
|
||
if [[ "$CLEAN_BUILD" = true ]]; then
|
||
print_header "Cleaning Build Artifacts"
|
||
|
||
if [[ "$SKIP_BACKEND" = false ]]; then
|
||
print_info "Cleaning backend..."
|
||
rm -rf "$BACKEND_SRC/target"
|
||
print_success "Backend cleaned"
|
||
fi
|
||
|
||
if [[ "$SKIP_FRONTEND" = false ]]; then
|
||
print_info "Cleaning frontend..."
|
||
rm -rf "$FRONTEND_SRC/dist"
|
||
rm -rf "$FRONTEND_SRC/node_modules/.vite"
|
||
print_success "Frontend cleaned"
|
||
fi
|
||
|
||
print_info "Cleaning ISO build directory..."
|
||
rm -rf "$BUILD_DIR"
|
||
rm -rf "$SCRIPT_DIR/image-recipe/iso-workdir"
|
||
rm -rf "$SCRIPT_DIR/image-recipe/results"
|
||
print_success "ISO build artifacts cleaned"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Step 2: Build Backend
|
||
# =============================================================================
|
||
|
||
if [[ "$SKIP_BACKEND" = false ]]; then
|
||
print_header "Building Backend (Rust)"
|
||
|
||
if [[ "$BUILD_MODE" == "local" ]]; then
|
||
print_info "Building backend locally..."
|
||
cd "$BACKEND_SRC"
|
||
|
||
if ! check_command cargo; then
|
||
print_error "Rust/Cargo not installed. Install from: https://rustup.rs"
|
||
exit 1
|
||
fi
|
||
|
||
cargo build --release
|
||
|
||
# Copy to build directory
|
||
mkdir -p "$BUILD_DIR/backend"
|
||
cp target/release/archipelago "$BUILD_DIR/backend/"
|
||
chmod +x "$BUILD_DIR/backend/archipelago"
|
||
|
||
print_success "Backend built locally"
|
||
|
||
elif [[ "$BUILD_MODE" == "remote" ]]; then
|
||
print_info "Building backend on remote server: $REMOTE_HOST"
|
||
|
||
# Sync source code to remote
|
||
print_info "Syncing source code to remote..."
|
||
ssh "$REMOTE_HOST" "mkdir -p ~/archy-build"
|
||
rsync -az --delete \
|
||
--exclude 'target/' \
|
||
--exclude 'node_modules/' \
|
||
--exclude '.git/' \
|
||
"$BACKEND_SRC/" "$REMOTE_HOST:~/archy-build/core/archipelago/"
|
||
|
||
# Build on remote
|
||
print_info "Compiling backend on remote..."
|
||
ssh "$REMOTE_HOST" "cd ~/archy-build/core/archipelago && cargo build --release"
|
||
|
||
# Copy binary back
|
||
mkdir -p "$BUILD_DIR/backend"
|
||
print_info "Copying binary back to local..."
|
||
scp "$REMOTE_HOST:~/archy-build/core/archipelago/target/release/archipelago" "$BUILD_DIR/backend/"
|
||
chmod +x "$BUILD_DIR/backend/archipelago"
|
||
|
||
print_success "Backend built on remote server"
|
||
fi
|
||
|
||
# Verify binary
|
||
if [[ ! -f "$BUILD_DIR/backend/archipelago" ]]; then
|
||
print_error "Backend binary not found after build!"
|
||
exit 1
|
||
fi
|
||
|
||
BINARY_SIZE=$(du -h "$BUILD_DIR/backend/archipelago" | awk '{print $1}')
|
||
print_success "Backend binary ready ($BINARY_SIZE)"
|
||
else
|
||
print_warning "Skipping backend build (using existing binary)"
|
||
if [[ ! -f "$BUILD_DIR/backend/archipelago" ]]; then
|
||
print_error "No existing backend binary found at $BUILD_DIR/backend/archipelago"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Step 3: Build Frontend
|
||
# =============================================================================
|
||
|
||
if [[ "$SKIP_FRONTEND" = false ]]; then
|
||
print_header "Building Frontend (Vue.js)"
|
||
|
||
cd "$FRONTEND_SRC"
|
||
|
||
if ! check_command npm; then
|
||
print_error "Node.js/npm not installed. Install from: https://nodejs.org"
|
||
exit 1
|
||
fi
|
||
|
||
# Install dependencies if needed
|
||
if [[ ! -d "node_modules" ]] || [[ "$CLEAN_BUILD" = true ]]; then
|
||
print_info "Installing dependencies..."
|
||
npm install
|
||
fi
|
||
|
||
# Build frontend
|
||
print_info "Building frontend..."
|
||
npm run build
|
||
|
||
# Copy to build directory
|
||
mkdir -p "$BUILD_DIR/frontend"
|
||
cp -r dist/* "$BUILD_DIR/frontend/"
|
||
|
||
print_success "Frontend built"
|
||
|
||
# Verify dist
|
||
if [[ ! -d "$BUILD_DIR/frontend" ]] || [[ -z "$(ls -A "$BUILD_DIR/frontend")" ]]; then
|
||
print_error "Frontend build directory is empty!"
|
||
exit 1
|
||
fi
|
||
|
||
DIST_SIZE=$(du -sh "$BUILD_DIR/frontend" | awk '{print $1}')
|
||
print_success "Frontend assets ready ($DIST_SIZE)"
|
||
else
|
||
print_warning "Skipping frontend build (using existing dist)"
|
||
if [[ ! -d "$BUILD_DIR/frontend" ]] || [[ -z "$(ls -A "$BUILD_DIR/frontend")" ]]; then
|
||
print_error "No existing frontend build found at $BUILD_DIR/frontend"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Step 4: Build ISO
|
||
# =============================================================================
|
||
|
||
print_header "Building Bootable ISO"
|
||
|
||
# Check if running on remote or need to transfer
|
||
if [[ "$BUILD_MODE" == "remote" ]]; then
|
||
print_info "Transferring build artifacts to remote server..."
|
||
|
||
# Sync entire project to remote
|
||
ssh "$REMOTE_HOST" "mkdir -p ~/archy"
|
||
rsync -az --delete \
|
||
--exclude '.git/' \
|
||
--exclude 'node_modules/' \
|
||
--exclude 'core/target/' \
|
||
--exclude 'core/parmanode/' \
|
||
"$SCRIPT_DIR/" "$REMOTE_HOST:~/archy/"
|
||
|
||
print_success "Files synced to remote"
|
||
|
||
print_info "Running ISO build on remote server (auto-installer, DEV_SERVER=$REMOTE_HOST)..."
|
||
ssh -t "$REMOTE_HOST" "cd ~/archy/image-recipe && DEV_SERVER=$REMOTE_HOST sudo -E bash build-auto-installer-iso.sh" || {
|
||
print_error "ISO build failed on remote server"
|
||
exit 1
|
||
}
|
||
|
||
print_success "ISO built on remote server"
|
||
|
||
# Copy ISO back to local
|
||
ISO_NAME="archipelago-installer-x86_64.iso"
|
||
print_info "Copying ISO back to local machine..."
|
||
mkdir -p "$SCRIPT_DIR/image-recipe/results"
|
||
scp "$REMOTE_HOST:~/archy/image-recipe/results/$ISO_NAME" "$SCRIPT_DIR/image-recipe/results/"
|
||
|
||
ISO_PATH="$SCRIPT_DIR/image-recipe/results/$ISO_NAME"
|
||
|
||
else
|
||
# Local build
|
||
print_info "Running ISO build locally (auto-installer)..."
|
||
cd "$SCRIPT_DIR/image-recipe"
|
||
sudo bash build-auto-installer-iso.sh
|
||
|
||
ISO_PATH="$SCRIPT_DIR/image-recipe/results/archipelago-installer-x86_64.iso"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Step 5: Verify and Report
|
||
# =============================================================================
|
||
|
||
print_header "Build Complete!"
|
||
|
||
if [[ -f "$ISO_PATH" ]]; then
|
||
ISO_SIZE=$(du -h "$ISO_PATH" | awk '{print $1}')
|
||
ISO_MD5=$(md5 -q "$ISO_PATH" 2>/dev/null || md5sum "$ISO_PATH" | awk '{print $1}')
|
||
|
||
echo ""
|
||
echo -e "${GREEN}✅ ISO ready for flashing!${NC}"
|
||
echo ""
|
||
echo -e " 📀 ${BLUE}ISO:${NC} $ISO_PATH"
|
||
echo -e " 📏 ${BLUE}Size:${NC} $ISO_SIZE"
|
||
echo -e " 🔐 ${BLUE}MD5:${NC} $ISO_MD5"
|
||
echo ""
|
||
echo -e "${YELLOW}Next steps:${NC}"
|
||
echo ""
|
||
echo " 1. Insert USB drive"
|
||
echo " 2. Find device: ${BLUE}diskutil list${NC}"
|
||
echo " 3. Flash ISO:"
|
||
echo ""
|
||
echo " ${BLUE}cd image-recipe && ./write-usb-dd.sh /dev/diskN${NC}"
|
||
echo ""
|
||
echo " 4. Boot from USB on target device"
|
||
echo ""
|
||
|
||
# Create a flash script for convenience
|
||
cat > "$SCRIPT_DIR/flash-to-usb.sh" <<'FLASH_EOF'
|
||
#!/bin/bash
|
||
# Quick USB flash script
|
||
cd "$(dirname "$0")/image-recipe" && ./write-usb-dd.sh "$@"
|
||
FLASH_EOF
|
||
chmod +x "$SCRIPT_DIR/flash-to-usb.sh"
|
||
|
||
print_success "Created convenience script: ./flash-to-usb.sh"
|
||
|
||
else
|
||
print_error "ISO not found at expected location: $ISO_PATH"
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Done!
|
||
# =============================================================================
|
||
|
||
echo ""
|
||
echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
|
||
echo -e "${GREEN}║ 🎉 Build Complete - Ready to Flash! ║${NC}"
|
||
echo -e "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
|
||
echo ""
|