- Added instructions to README.md for building an ISO from source and flashing it to USB. - Introduced a new RPC method for package installation, including security checks and container management. - Updated Docker and Podman integration in build scripts to support both container runtimes. - Enhanced Nginx configuration for improved timeout settings and WebSocket support. - Added new app metadata for additional applications in the Docker package scanner.
395 lines
12 KiB
Bash
Executable File
395 lines
12 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
|
||
#
|
||
|
||
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-debian-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..."
|
||
ssh -t "$REMOTE_HOST" "cd ~/archy/image-recipe && sudo bash build-debian-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-debian-12-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..."
|
||
cd "$SCRIPT_DIR/image-recipe"
|
||
sudo bash build-debian-iso.sh
|
||
|
||
ISO_PATH="$SCRIPT_DIR/image-recipe/results/archipelago-debian-12-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 ""
|