2026-01-31 19:47:52 +00:00
|
|
|
#!/bin/bash
|
|
|
|
|
# Build Archipelago OS for specific hardware target
|
|
|
|
|
# Supports: start9-pure, hp-prodesk, dell-optiplex, generic
|
|
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
|
|
|
|
|
|
# Hardware target (default: generic)
|
|
|
|
|
HARDWARE_TARGET="${1:-generic}"
|
|
|
|
|
BUILD_TYPE="${2:-iso}"
|
|
|
|
|
|
|
|
|
|
ARCHIPELAGO_VERSION="${ARCHIPELAGO_VERSION:-0.1.0}"
|
|
|
|
|
ALPINE_VERSION="${ALPINE_VERSION:-3.19}"
|
|
|
|
|
ARCH="x86_64" # All supported hardware is x86_64
|
|
|
|
|
|
|
|
|
|
# Color output
|
|
|
|
|
GREEN='\033[0;32m'
|
|
|
|
|
BLUE='\033[0;34m'
|
|
|
|
|
YELLOW='\033[1;33m'
|
|
|
|
|
RED='\033[0;31m'
|
|
|
|
|
NC='\033[0m' # No Color
|
|
|
|
|
|
|
|
|
|
echo -e "${BLUE}🏗️ Archipelago OS Builder${NC}"
|
|
|
|
|
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
# Validate hardware target
|
|
|
|
|
case "$HARDWARE_TARGET" in
|
|
|
|
|
start9-pure|start9)
|
|
|
|
|
HARDWARE_NAME="Start9 Server Pure"
|
|
|
|
|
HARDWARE_PROFILE="start9-pure"
|
|
|
|
|
CPU_VENDOR="intel"
|
|
|
|
|
CPU_MODEL="i7-10710U"
|
|
|
|
|
RAM_MIN="32GB"
|
|
|
|
|
STORAGE_MIN="2TB"
|
|
|
|
|
NETWORK_INTERFACES="1x Gigabit Ethernet"
|
|
|
|
|
USB_PORTS="4x USB 3.0, 2x USB 2.0, 1x USB-C 3.1"
|
|
|
|
|
OPTIMIZATIONS="intel-graphics intel-networking nvme-ssd"
|
|
|
|
|
;;
|
|
|
|
|
hp-prodesk|prodesk)
|
|
|
|
|
HARDWARE_NAME="HP ProDesk 400 G4 DM"
|
|
|
|
|
HARDWARE_PROFILE="hp-prodesk"
|
|
|
|
|
CPU_VENDOR="intel"
|
|
|
|
|
CPU_MODEL="varies"
|
|
|
|
|
RAM_MIN="8GB"
|
|
|
|
|
STORAGE_MIN="128GB"
|
|
|
|
|
NETWORK_INTERFACES="1x Gigabit Ethernet"
|
|
|
|
|
USB_PORTS="4x USB 3.0, 2x USB 2.0"
|
|
|
|
|
OPTIMIZATIONS="intel-graphics intel-networking sata-ssd"
|
|
|
|
|
;;
|
|
|
|
|
dell-optiplex|optiplex)
|
|
|
|
|
HARDWARE_NAME="Dell OptiPlex"
|
|
|
|
|
HARDWARE_PROFILE="dell-optiplex"
|
|
|
|
|
CPU_VENDOR="intel"
|
|
|
|
|
CPU_MODEL="varies"
|
|
|
|
|
RAM_MIN="8GB"
|
|
|
|
|
STORAGE_MIN="128GB"
|
|
|
|
|
NETWORK_INTERFACES="1x Gigabit Ethernet"
|
|
|
|
|
USB_PORTS="Multiple USB ports"
|
|
|
|
|
OPTIMIZATIONS="intel-graphics intel-networking sata-ssd"
|
|
|
|
|
;;
|
|
|
|
|
generic)
|
|
|
|
|
HARDWARE_NAME="Generic x86_64"
|
|
|
|
|
HARDWARE_PROFILE="generic"
|
|
|
|
|
CPU_VENDOR="any"
|
|
|
|
|
CPU_MODEL="any"
|
|
|
|
|
RAM_MIN="8GB"
|
|
|
|
|
STORAGE_MIN="128GB"
|
|
|
|
|
NETWORK_INTERFACES="any"
|
|
|
|
|
USB_PORTS="any"
|
|
|
|
|
OPTIMIZATIONS="generic"
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo -e "${RED}❌ Unknown hardware target: $HARDWARE_TARGET${NC}"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Supported targets:"
|
|
|
|
|
echo " start9-pure - Start9 Server Pure (Intel i7-10710U)"
|
|
|
|
|
echo " hp-prodesk - HP ProDesk 400 G4 DM"
|
|
|
|
|
echo " dell-optiplex - Dell OptiPlex"
|
|
|
|
|
echo " generic - Generic x86_64 hardware"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Usage: $0 <hardware-target> [iso|disk]"
|
|
|
|
|
exit 1
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
echo -e "${GREEN}📋 Build Configuration${NC}"
|
|
|
|
|
echo -e "━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
|
echo -e " Hardware: ${YELLOW}${HARDWARE_NAME}${NC}"
|
|
|
|
|
echo -e " Profile: ${HARDWARE_PROFILE}"
|
|
|
|
|
echo -e " CPU: ${CPU_VENDOR} ${CPU_MODEL}"
|
|
|
|
|
echo -e " Min RAM: ${RAM_MIN}"
|
|
|
|
|
echo -e " Min Storage: ${STORAGE_MIN}"
|
|
|
|
|
echo -e " Network: ${NETWORK_INTERFACES}"
|
|
|
|
|
echo -e " Build Type: ${BUILD_TYPE}"
|
|
|
|
|
echo -e " Architecture: ${ARCH}"
|
|
|
|
|
echo -e " Version: ${ARCHIPELAGO_VERSION}"
|
|
|
|
|
echo -e " Alpine: ${ALPINE_VERSION}"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
# Create hardware-specific overlay
|
|
|
|
|
HARDWARE_OVERLAY_DIR="$SCRIPT_DIR/alpine-profile/overlay-${HARDWARE_PROFILE}"
|
|
|
|
|
mkdir -p "$HARDWARE_OVERLAY_DIR/etc/archipelago"
|
|
|
|
|
|
|
|
|
|
# Create hardware detection script
|
|
|
|
|
cat > "$HARDWARE_OVERLAY_DIR/etc/archipelago/hardware-info.sh" <<'EOF'
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
# Hardware detection and optimization script
|
|
|
|
|
# Auto-generated for specific hardware target
|
|
|
|
|
|
|
|
|
|
detect_hardware() {
|
|
|
|
|
echo "=== Hardware Detection ==="
|
|
|
|
|
|
|
|
|
|
# CPU info
|
|
|
|
|
if [ -f /proc/cpuinfo ]; then
|
|
|
|
|
echo "CPU: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)"
|
|
|
|
|
echo "Cores: $(grep -c processor /proc/cpuinfo)"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Memory
|
|
|
|
|
if [ -f /proc/meminfo ]; then
|
|
|
|
|
echo "Memory: $(grep MemTotal /proc/meminfo | awk '{printf "%.1f GB", $2/1024/1024}')"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Storage
|
|
|
|
|
if command -v lsblk >/dev/null 2>&1; then
|
|
|
|
|
echo "Storage:"
|
|
|
|
|
lsblk -d -o NAME,SIZE,TYPE | grep disk
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Network
|
|
|
|
|
if command -v ip >/dev/null 2>&1; then
|
|
|
|
|
echo "Network interfaces:"
|
|
|
|
|
ip -br link show | grep -v lo
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# PCI devices (for hardware identification)
|
|
|
|
|
if command -v lspci >/dev/null 2>&1; then
|
|
|
|
|
echo "PCI devices:"
|
|
|
|
|
lspci | grep -E "VGA|Ethernet|Network"
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optimize_for_hardware() {
|
|
|
|
|
echo "=== Hardware Optimization ==="
|
|
|
|
|
|
|
|
|
|
# Load Intel microcode if Intel CPU
|
|
|
|
|
if grep -q Intel /proc/cpuinfo; then
|
|
|
|
|
echo "Intel CPU detected, loading microcode..."
|
|
|
|
|
modprobe intel_rapl_common 2>/dev/null || true
|
|
|
|
|
modprobe intel_powerclamp 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Enable hardware acceleration for graphics
|
|
|
|
|
if lspci | grep -q "Intel.*Graphics"; then
|
|
|
|
|
echo "Intel Graphics detected"
|
|
|
|
|
modprobe i915 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Optimize for NVMe if present
|
|
|
|
|
if [ -e /dev/nvme0n1 ]; then
|
|
|
|
|
echo "NVMe SSD detected, optimizing..."
|
|
|
|
|
echo none > /sys/block/nvme0n1/queue/scheduler 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Optimize for SATA SSD if present
|
|
|
|
|
if [ -e /dev/sda ]; then
|
|
|
|
|
if hdparm -I /dev/sda 2>/dev/null | grep -q "Solid State"; then
|
|
|
|
|
echo "SATA SSD detected, optimizing..."
|
|
|
|
|
echo deadline > /sys/block/sda/queue/scheduler 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Run detection
|
|
|
|
|
detect_hardware
|
|
|
|
|
optimize_for_hardware
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
chmod +x "$HARDWARE_OVERLAY_DIR/etc/archipelago/hardware-info.sh"
|
|
|
|
|
|
|
|
|
|
# Create hardware-specific config
|
|
|
|
|
cat > "$HARDWARE_OVERLAY_DIR/etc/archipelago/hardware.toml" <<EOF
|
|
|
|
|
# Hardware profile for ${HARDWARE_NAME}
|
|
|
|
|
# Auto-generated during build
|
|
|
|
|
|
|
|
|
|
[hardware]
|
|
|
|
|
target = "${HARDWARE_PROFILE}"
|
|
|
|
|
name = "${HARDWARE_NAME}"
|
|
|
|
|
cpu_vendor = "${CPU_VENDOR}"
|
|
|
|
|
cpu_model = "${CPU_MODEL}"
|
|
|
|
|
min_ram = "${RAM_MIN}"
|
|
|
|
|
min_storage = "${STORAGE_MIN}"
|
|
|
|
|
architecture = "${ARCH}"
|
|
|
|
|
|
|
|
|
|
[optimizations]
|
|
|
|
|
enabled = ${OPTIMIZATIONS}
|
|
|
|
|
|
|
|
|
|
[network]
|
|
|
|
|
interfaces = "${NETWORK_INTERFACES}"
|
|
|
|
|
|
|
|
|
|
[usb]
|
|
|
|
|
ports = "${USB_PORTS}"
|
|
|
|
|
|
|
|
|
|
[build]
|
|
|
|
|
version = "${ARCHIPELAGO_VERSION}"
|
|
|
|
|
alpine_version = "${ALPINE_VERSION}"
|
|
|
|
|
build_date = "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
|
|
|
build_type = "${BUILD_TYPE}"
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
echo -e "${GREEN}✓${NC} Hardware profile created: ${HARDWARE_PROFILE}"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
# Create first-boot hardware detection service
|
|
|
|
|
mkdir -p "$HARDWARE_OVERLAY_DIR/etc/local.d"
|
|
|
|
|
cat > "$HARDWARE_OVERLAY_DIR/etc/local.d/00-hardware-detect.start" <<'EOF'
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
# First boot hardware detection and optimization
|
|
|
|
|
|
|
|
|
|
HARDWARE_INFO="/etc/archipelago/hardware-info.sh"
|
|
|
|
|
|
|
|
|
|
if [ -x "$HARDWARE_INFO" ]; then
|
|
|
|
|
echo "🔍 Detecting hardware..."
|
|
|
|
|
$HARDWARE_INFO > /var/log/archipelago-hardware.log 2>&1
|
|
|
|
|
echo "✓ Hardware detection complete"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Create system info file
|
|
|
|
|
cat > /etc/archipelago/system-info.txt <<INFO
|
|
|
|
|
Archipelago OS System Information
|
|
|
|
|
Generated: $(date)
|
|
|
|
|
|
|
|
|
|
$(cat /etc/archipelago/hardware.toml 2>/dev/null)
|
|
|
|
|
|
|
|
|
|
Runtime Detection:
|
|
|
|
|
$(cat /var/log/archipelago-hardware.log 2>/dev/null)
|
|
|
|
|
INFO
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
chmod +x "$HARDWARE_OVERLAY_DIR/etc/local.d/00-hardware-detect.start"
|
|
|
|
|
|
|
|
|
|
# Merge with base overlay
|
|
|
|
|
echo -e "${BLUE}📦 Merging overlays...${NC}"
|
|
|
|
|
MERGED_OVERLAY="$SCRIPT_DIR/alpine-profile/overlay-merged"
|
|
|
|
|
rm -rf "$MERGED_OVERLAY"
|
|
|
|
|
mkdir -p "$MERGED_OVERLAY"
|
|
|
|
|
|
|
|
|
|
# Copy base overlay
|
|
|
|
|
if [ -d "$SCRIPT_DIR/alpine-profile/overlay" ]; then
|
|
|
|
|
cp -a "$SCRIPT_DIR/alpine-profile/overlay/"* "$MERGED_OVERLAY/"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Copy hardware-specific overlay (overwrites base)
|
|
|
|
|
if [ -d "$HARDWARE_OVERLAY_DIR" ]; then
|
|
|
|
|
cp -a "$HARDWARE_OVERLAY_DIR/"* "$MERGED_OVERLAY/"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo -e "${GREEN}✓${NC} Overlays merged"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
# Set environment variables for build
|
|
|
|
|
export HARDWARE_TARGET="$HARDWARE_PROFILE"
|
|
|
|
|
export HARDWARE_NAME="$HARDWARE_NAME"
|
|
|
|
|
export ARCHIPELAGO_VERSION
|
|
|
|
|
export ALPINE_VERSION
|
|
|
|
|
export ARCH
|
|
|
|
|
export BUILD_TYPE
|
|
|
|
|
|
2026-01-31 22:56:39 +00:00
|
|
|
# Determine build method - use custom ISO builder
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e "${BLUE}🔨 Building custom ISO from Alpine base...${NC}"
|
|
|
|
|
"$SCRIPT_DIR/build-custom-iso.sh" || {
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e "${RED}❌ ISO build failed${NC}"
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
2026-01-31 19:47:52 +00:00
|
|
|
|
2026-01-31 22:56:39 +00:00
|
|
|
# Rename output with hardware target
|
2026-01-31 19:47:52 +00:00
|
|
|
OUTPUT_DIR="$SCRIPT_DIR/results"
|
2026-01-31 22:56:39 +00:00
|
|
|
if [ -f "$OUTPUT_DIR/archipelago-${ALPINE_VERSION}-${ARCH}.iso" ]; then
|
|
|
|
|
mv "$OUTPUT_DIR/archipelago-${ALPINE_VERSION}-${ARCH}.iso" \
|
|
|
|
|
"$OUTPUT_DIR/archipelago-${ALPINE_VERSION}-${HARDWARE_PROFILE}-${ARCH}.iso"
|
2026-01-31 19:47:52 +00:00
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
|
|
|
echo -e "${GREEN}✅ Build Complete!${NC}"
|
|
|
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e " ${YELLOW}Hardware:${NC} ${HARDWARE_NAME}"
|
2026-01-31 22:56:39 +00:00
|
|
|
echo -e " ${YELLOW}ISO File:${NC} archipelago-${ALPINE_VERSION}-${HARDWARE_PROFILE}-${ARCH}.iso"
|
2026-01-31 19:47:52 +00:00
|
|
|
echo -e " ${YELLOW}Location:${NC} ${OUTPUT_DIR}/"
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e "${BLUE}Next Steps:${NC}"
|
|
|
|
|
echo -e " 1. Flash ISO to USB drive:"
|
2026-01-31 22:56:39 +00:00
|
|
|
echo -e " ${YELLOW}sudo dd if=${OUTPUT_DIR}/archipelago-${ALPINE_VERSION}-${HARDWARE_PROFILE}-${ARCH}.iso of=/dev/sdX bs=1M${NC}"
|
2026-01-31 19:47:52 +00:00
|
|
|
echo ""
|
|
|
|
|
echo -e " 2. Boot ${HARDWARE_NAME} from USB"
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e " 3. Access Archipelago UI at: ${YELLOW}http://device-ip:8100${NC}"
|
|
|
|
|
echo ""
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Create build manifest
|
|
|
|
|
cat > "$OUTPUT_DIR/BUILD_MANIFEST_${HARDWARE_PROFILE}.txt" <<MANIFEST
|
|
|
|
|
Archipelago OS Build Manifest
|
|
|
|
|
═════════════════════════════
|
|
|
|
|
|
|
|
|
|
Build Information
|
|
|
|
|
─────────────────
|
|
|
|
|
Version: ${ARCHIPELAGO_VERSION}
|
|
|
|
|
Alpine Version: ${ALPINE_VERSION}
|
|
|
|
|
Architecture: ${ARCH}
|
|
|
|
|
Build Type: ${BUILD_TYPE}
|
|
|
|
|
Build Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
|
|
|
Build Host: $(hostname)
|
|
|
|
|
|
|
|
|
|
Hardware Target
|
|
|
|
|
───────────────
|
|
|
|
|
Profile: ${HARDWARE_PROFILE}
|
|
|
|
|
Name: ${HARDWARE_NAME}
|
|
|
|
|
CPU: ${CPU_VENDOR} ${CPU_MODEL}
|
|
|
|
|
Minimum RAM: ${RAM_MIN}
|
|
|
|
|
Minimum Storage: ${STORAGE_MIN}
|
|
|
|
|
Network: ${NETWORK_INTERFACES}
|
|
|
|
|
USB Ports: ${USB_PORTS}
|
|
|
|
|
|
|
|
|
|
Optimizations
|
|
|
|
|
─────────────
|
|
|
|
|
${OPTIMIZATIONS}
|
|
|
|
|
|
|
|
|
|
Files Generated
|
|
|
|
|
───────────────
|
|
|
|
|
ISO: archipelago-${ARCHIPELAGO_VERSION}-${HARDWARE_PROFILE}-${ARCH}.iso
|
|
|
|
|
$([ -f "$OUTPUT_DIR/archipelago-${ARCHIPELAGO_VERSION}-${HARDWARE_PROFILE}-${ARCH}.img" ] && echo "IMG: archipelago-${ARCHIPELAGO_VERSION}-${HARDWARE_PROFILE}-${ARCH}.img")
|
|
|
|
|
|
|
|
|
|
Installation
|
|
|
|
|
────────────
|
|
|
|
|
1. Flash to USB:
|
|
|
|
|
sudo dd if=archipelago-${ARCHIPELAGO_VERSION}-${HARDWARE_PROFILE}-${ARCH}.iso of=/dev/sdX bs=1M
|
|
|
|
|
|
|
|
|
|
2. Boot ${HARDWARE_NAME} from USB
|
|
|
|
|
|
|
|
|
|
3. Follow on-screen installation
|
|
|
|
|
|
|
|
|
|
4. Access UI at http://device-ip:8100
|
|
|
|
|
|
|
|
|
|
Hardware Requirements
|
|
|
|
|
────────────────────
|
|
|
|
|
- CPU: ${CPU_VENDOR} ${CPU_MODEL}
|
|
|
|
|
- RAM: ${RAM_MIN} minimum
|
|
|
|
|
- Storage: ${STORAGE_MIN} minimum
|
|
|
|
|
- Network: ${NETWORK_INTERFACES}
|
|
|
|
|
- Boot: UEFI (Legacy BIOS supported)
|
|
|
|
|
|
|
|
|
|
Support
|
|
|
|
|
───────
|
|
|
|
|
- Documentation: docs/
|
|
|
|
|
- Issues: GitHub Issues
|
|
|
|
|
- Community: Discord (coming soon)
|
|
|
|
|
|
|
|
|
|
Built with ❤️ by the Archipelago team
|
|
|
|
|
MANIFEST
|
|
|
|
|
|
|
|
|
|
echo -e "${GREEN}✓${NC} Build manifest created"
|
|
|
|
|
echo ""
|