- Replaced OS-specific build method with a custom ISO builder in the build-for-hardware.sh script. - Updated output file naming to reflect the correct Alpine version in the build process. - Adjusted build dates in hardware configuration files for HP ProDesk, merged, and Start9 Pure profiles to the latest timestamp.
462 lines
14 KiB
Bash
Executable File
462 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
|
# Custom ISO builder that works on ARM Mac by modifying pre-built Alpine ISO
|
|
# instead of building from scratch
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ALPINE_VERSION="${ALPINE_VERSION:-3.19}"
|
|
ARCH="${ARCH:-x86_64}"
|
|
ISO_URL="https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION}/releases/${ARCH}/alpine-standard-${ALPINE_VERSION}.0-${ARCH}.iso"
|
|
WORK_DIR="$SCRIPT_DIR/build/iso-custom"
|
|
OUTPUT_DIR="$SCRIPT_DIR/results"
|
|
|
|
echo "🏔️ Building custom Archipelago ISO from Alpine base"
|
|
echo ""
|
|
echo "📋 Configuration:"
|
|
echo " Alpine Version: $ALPINE_VERSION"
|
|
echo " Architecture: $ARCH"
|
|
echo " Base ISO URL: $ISO_URL"
|
|
echo ""
|
|
|
|
# Create work directories
|
|
mkdir -p "$WORK_DIR"
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
# Download Alpine base ISO if not exists
|
|
BASE_ISO="$WORK_DIR/alpine-base.iso"
|
|
if [ ! -f "$BASE_ISO" ]; then
|
|
echo "📥 Downloading Alpine base ISO..."
|
|
curl -L -o "$BASE_ISO" "$ISO_URL" || {
|
|
echo "❌ Failed to download Alpine ISO"
|
|
exit 1
|
|
}
|
|
echo "✅ Downloaded base ISO"
|
|
else
|
|
echo "✅ Using cached base ISO"
|
|
fi
|
|
|
|
# Extract ISO contents
|
|
echo "📦 Extracting ISO contents..."
|
|
CUSTOM_DIR="$WORK_DIR/custom"
|
|
rm -rf "$CUSTOM_DIR"
|
|
mkdir -p "$CUSTOM_DIR"
|
|
|
|
# Use 7zip to extract ISO (works on both macOS and Linux)
|
|
if command -v 7z >/dev/null 2>&1; then
|
|
7z x "$BASE_ISO" -o"$CUSTOM_DIR" -y >/dev/null || {
|
|
echo "❌ Failed to extract ISO with 7zip"
|
|
exit 1
|
|
}
|
|
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|
# Fallback: Try mounting on macOS
|
|
MOUNT_POINT="$WORK_DIR/mnt"
|
|
mkdir -p "$MOUNT_POINT"
|
|
hdiutil attach "$BASE_ISO" -mountpoint "$MOUNT_POINT" -readonly && {
|
|
rsync -a "$MOUNT_POINT"/ "$CUSTOM_DIR"/
|
|
hdiutil detach "$MOUNT_POINT"
|
|
} || {
|
|
echo "❌ Failed to extract ISO. Install p7zip: brew install p7zip"
|
|
exit 1
|
|
}
|
|
else
|
|
# On Linux, mount the ISO
|
|
MOUNT_POINT="$WORK_DIR/mnt"
|
|
mkdir -p "$MOUNT_POINT"
|
|
sudo mount -o loop "$BASE_ISO" "$MOUNT_POINT" && {
|
|
cp -a "$MOUNT_POINT"/* "$CUSTOM_DIR"/
|
|
sudo umount "$MOUNT_POINT"
|
|
} || {
|
|
echo "❌ Failed to mount ISO"
|
|
exit 1
|
|
}
|
|
fi
|
|
|
|
echo "✅ ISO contents extracted"
|
|
|
|
# Add custom packages
|
|
echo "📦 Adding custom packages..."
|
|
APKS_DIR="$CUSTOM_DIR/apks/$(uname -m)"
|
|
mkdir -p "$APKS_DIR"
|
|
|
|
# Create a custom apk repository file
|
|
cat > "$CUSTOM_DIR/archipelago.list" <<'EOF'
|
|
# Archipelago custom packages
|
|
# These will be installed during setup-alpine or via apk add
|
|
|
|
# Container runtime
|
|
podman
|
|
crun
|
|
fuse-overlayfs
|
|
slirp4netns
|
|
|
|
# Web server
|
|
nginx
|
|
|
|
# SSH server
|
|
openssh
|
|
|
|
# Networking
|
|
iptables
|
|
iproute2
|
|
EOF
|
|
|
|
# Create automated installation script
|
|
echo "📝 Creating installation script..."
|
|
mkdir -p "$CUSTOM_DIR/archipelago"
|
|
cat > "$CUSTOM_DIR/archipelago/install.sh" <<'INSTALL_EOF'
|
|
#!/bin/sh
|
|
# Archipelago automated installation script
|
|
|
|
set -e
|
|
|
|
echo "🏝️ Installing Archipelago Bitcoin Node OS"
|
|
echo ""
|
|
|
|
# Install required packages
|
|
echo "📦 Installing packages..."
|
|
apk add --no-cache \
|
|
podman \
|
|
crun \
|
|
fuse-overlayfs \
|
|
slirp4netns \
|
|
nginx \
|
|
openssh \
|
|
iptables \
|
|
iproute2 \
|
|
bash \
|
|
curl
|
|
|
|
# Create archipelago user
|
|
echo "👤 Creating archipelago user..."
|
|
if ! id archipelago >/dev/null 2>&1; then
|
|
adduser -D -s /bin/bash archipelago
|
|
echo "archipelago:archipelago" | chpasswd
|
|
fi
|
|
|
|
# Setup Podman for archipelago user
|
|
echo "🐳 Setting up Podman..."
|
|
mkdir -p /home/archipelago/.config/containers
|
|
chown -R archipelago:archipelago /home/archipelago
|
|
|
|
# Create data directories
|
|
echo "📁 Creating data directories..."
|
|
mkdir -p /var/lib/archipelago/{apps,secrets,logs,backups}
|
|
chown -R archipelago:archipelago /var/lib/archipelago
|
|
|
|
# Install Archipelago backend if available
|
|
if [ -f /media/cdrom/archipelago/bin/archipelago ]; then
|
|
echo "🦀 Installing Archipelago backend..."
|
|
mkdir -p /usr/local/bin
|
|
cp /media/cdrom/archipelago/bin/archipelago /usr/local/bin/
|
|
chmod +x /usr/local/bin/archipelago
|
|
echo "✅ Backend installed"
|
|
fi
|
|
|
|
# Install Archipelago frontend if available
|
|
if [ -d /media/cdrom/archipelago/web ]; then
|
|
echo "🎨 Installing Archipelago web UI..."
|
|
mkdir -p /usr/share/archipelago/web
|
|
cp -r /media/cdrom/archipelago/web/* /usr/share/archipelago/web/
|
|
|
|
# Configure nginx
|
|
cat > /etc/nginx/http.d/archipelago.conf <<'NGINX_EOF'
|
|
server {
|
|
listen 8100;
|
|
server_name _;
|
|
|
|
root /usr/share/archipelago/web;
|
|
index index.html;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
# Proxy API requests to backend
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:8101/;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection 'upgrade';
|
|
proxy_set_header Host $host;
|
|
proxy_cache_bypass $http_upgrade;
|
|
}
|
|
}
|
|
NGINX_EOF
|
|
|
|
rc-update add nginx default
|
|
echo "✅ Web UI installed"
|
|
fi
|
|
|
|
# Create Archipelago service
|
|
if [ -f /usr/local/bin/archipelago ]; then
|
|
echo "⚙️ Creating Archipelago service..."
|
|
cat > /etc/init.d/archipelago <<'SERVICE_EOF'
|
|
#!/sbin/openrc-run
|
|
|
|
name="Archipelago"
|
|
description="Archipelago Bitcoin Node OS Backend"
|
|
command="/usr/local/bin/archipelago"
|
|
command_background=true
|
|
pidfile="/run/archipelago.pid"
|
|
|
|
depend() {
|
|
need net
|
|
after networking
|
|
}
|
|
SERVICE_EOF
|
|
|
|
chmod +x /etc/init.d/archipelago
|
|
rc-update add archipelago default
|
|
echo "✅ Archipelago service created"
|
|
fi
|
|
|
|
# Install app manifests if available
|
|
if [ -d /media/cdrom/archipelago/apps ]; then
|
|
echo "📦 Installing app manifests..."
|
|
mkdir -p /var/lib/archipelago/manifests
|
|
cp -r /media/cdrom/archipelago/apps/* /var/lib/archipelago/manifests/
|
|
chown -R archipelago:archipelago /var/lib/archipelago/manifests
|
|
echo "✅ App manifests installed"
|
|
fi
|
|
|
|
# Configure networking (DHCP)
|
|
echo "🌐 Configuring network..."
|
|
cat > /etc/network/interfaces <<'NET_EOF'
|
|
auto lo
|
|
iface lo inet loopback
|
|
|
|
auto eth0
|
|
iface eth0 inet dhcp
|
|
|
|
auto enp0s3
|
|
iface enp0s3 inet dhcp
|
|
|
|
auto enp0s25
|
|
iface enp0s25 inet dhcp
|
|
NET_EOF
|
|
|
|
# Enable services
|
|
echo "⚙️ Enabling services..."
|
|
rc-update add networking default
|
|
rc-update add sshd default
|
|
rc-update add local default
|
|
|
|
# Set hostname
|
|
echo "archipelago" > /etc/hostname
|
|
|
|
# Configure SSH
|
|
echo "🔐 Configuring SSH..."
|
|
sed -i 's/#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
|
|
|
# Create welcome message
|
|
cat > /etc/motd <<'MOTD_EOF'
|
|
|
|
╔═══════════════════════════════════════════════════════════╗
|
|
║ ║
|
|
║ 🏝️ ARCHIPELAGO BITCOIN NODE OS ║
|
|
║ ║
|
|
║ A sovereign computing platform built on Alpine Linux ║
|
|
║ ║
|
|
╚═══════════════════════════════════════════════════════════╝
|
|
|
|
Default user: archipelago
|
|
Default pass: archipelago (CHANGE THIS IMMEDIATELY!)
|
|
|
|
To access the web UI:
|
|
http://$(hostname -i):8100
|
|
|
|
To start Archipelago:
|
|
sudo systemctl start archipelago
|
|
|
|
Documentation: /usr/share/doc/archipelago/
|
|
|
|
MOTD_EOF
|
|
|
|
echo ""
|
|
echo "✅ Archipelago installation complete!"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Reboot the system"
|
|
echo " 2. Login with user: archipelago, pass: archipelago"
|
|
echo " 3. Change the default password: passwd"
|
|
echo " 4. Access web UI at http://<your-ip>:8100"
|
|
echo ""
|
|
|
|
INSTALL_EOF
|
|
|
|
chmod +x "$CUSTOM_DIR/archipelago/install.sh"
|
|
|
|
# Create README
|
|
cat > "$CUSTOM_DIR/archipelago/README.txt" <<'README_EOF'
|
|
ARCHIPELAGO BITCOIN NODE OS
|
|
===========================
|
|
|
|
This is a customized Alpine Linux ISO with Archipelago packages.
|
|
|
|
INSTALLATION:
|
|
1. Boot from this USB/ISO
|
|
2. Login as root (no password)
|
|
3. Run: setup-alpine
|
|
4. Follow the prompts to install Alpine
|
|
5. After installation, run: sh /media/*/archipelago/install.sh
|
|
6. Reboot
|
|
|
|
QUICK INSTALL:
|
|
For automated installation on dedicated hardware:
|
|
1. Boot from USB/ISO
|
|
2. Login as root
|
|
3. Run: sh /media/*/archipelago/install.sh
|
|
4. This will set up Alpine + Archipelago automatically
|
|
|
|
For more information, visit:
|
|
https://github.com/your-repo/archipelago
|
|
|
|
README_EOF
|
|
|
|
# Modify boot configuration to show Archipelago branding
|
|
if [ -f "$CUSTOM_DIR/boot/grub/grub.cfg" ]; then
|
|
echo "⚙️ Customizing boot menu..."
|
|
sed -i.bak 's/Alpine Linux/Archipelago Bitcoin Node OS/g' "$CUSTOM_DIR/boot/grub/grub.cfg" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ -f "$CUSTOM_DIR/boot/syslinux/syslinux.cfg" ]; then
|
|
sed -i.bak 's/Alpine Linux/Archipelago Bitcoin Node OS/g' "$CUSTOM_DIR/boot/syslinux/syslinux.cfg" 2>/dev/null || true
|
|
fi
|
|
|
|
# Include Archipelago backend if available
|
|
if [ -n "$INCLUDE_BACKEND" ] && [ -f "$INCLUDE_BACKEND" ]; then
|
|
echo "🦀 Including Archipelago backend..."
|
|
mkdir -p "$CUSTOM_DIR/archipelago/bin"
|
|
cp "$INCLUDE_BACKEND" "$CUSTOM_DIR/archipelago/bin/"
|
|
chmod +x "$CUSTOM_DIR/archipelago/bin/archipelago"
|
|
echo "✅ Backend included: $(du -h "$INCLUDE_BACKEND" | cut -f1)"
|
|
fi
|
|
|
|
# Include Archipelago frontend if available
|
|
if [ -n "$INCLUDE_FRONTEND" ] && [ -d "$INCLUDE_FRONTEND" ]; then
|
|
echo "🎨 Including Archipelago frontend..."
|
|
mkdir -p "$CUSTOM_DIR/archipelago/web"
|
|
cp -r "$INCLUDE_FRONTEND"/* "$CUSTOM_DIR/archipelago/web/"
|
|
echo "✅ Frontend included"
|
|
fi
|
|
|
|
# Include app manifests if available
|
|
APPS_DIR="$(dirname "$0")/../apps"
|
|
if [ -d "$APPS_DIR" ]; then
|
|
echo "📦 Including app manifests..."
|
|
mkdir -p "$CUSTOM_DIR/archipelago/apps"
|
|
# Copy all app directories with manifest.yml files
|
|
find "$APPS_DIR" -maxdepth 1 -type d -exec test -f {}/manifest.yml \; -exec cp -r {} "$CUSTOM_DIR/archipelago/apps/" \;
|
|
APP_COUNT=$(find "$CUSTOM_DIR/archipelago/apps" -name "manifest.yml" | wc -l | tr -d ' ')
|
|
echo "✅ Included $APP_COUNT app manifests"
|
|
fi
|
|
|
|
# Create the ISO
|
|
OUTPUT_ISO="$OUTPUT_DIR/archipelago-${ALPINE_VERSION}-${ARCH}.iso"
|
|
echo ""
|
|
echo "🔥 Creating final ISO..."
|
|
|
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
# On macOS, use xorriso for hybrid BIOS+UEFI bootable ISO
|
|
if command -v xorriso >/dev/null 2>&1; then
|
|
# Try dual-boot (BIOS + UEFI) if EFI bootloader exists
|
|
if [ -f "$CUSTOM_DIR/boot/grub/grub.cfg" ] || [ -d "$CUSTOM_DIR/efi" ] || [ -d "$CUSTOM_DIR/EFI" ]; then
|
|
echo "🔄 Creating hybrid BIOS+UEFI bootable ISO..."
|
|
xorriso -as mkisofs -o "$OUTPUT_ISO" \
|
|
-volid "ARCHIPELAGO" \
|
|
-J -R \
|
|
-c boot/syslinux/boot.cat \
|
|
-b boot/syslinux/isolinux.bin \
|
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
|
-eltorito-alt-boot \
|
|
-e boot/grub/efi.img \
|
|
-no-emul-boot \
|
|
-isohybrid-gpt-basdat \
|
|
-isohybrid-mbr "$CUSTOM_DIR/boot/syslinux/isohdpfx.bin" \
|
|
"$CUSTOM_DIR" 2>&1 | grep -v "xorriso : UPDATE" || {
|
|
echo "⚠️ Dual-boot failed, trying BIOS-only..."
|
|
xorriso -as mkisofs -o "$OUTPUT_ISO" \
|
|
-volid "ARCHIPELAGO" \
|
|
-J -R \
|
|
-c boot/syslinux/boot.cat \
|
|
-b boot/syslinux/isolinux.bin \
|
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
|
-isohybrid-mbr "$CUSTOM_DIR/boot/syslinux/isohdpfx.bin" \
|
|
"$CUSTOM_DIR" 2>&1 | grep -v "xorriso : UPDATE"
|
|
}
|
|
else
|
|
echo "🔄 Creating BIOS-only bootable ISO..."
|
|
xorriso -as mkisofs -o "$OUTPUT_ISO" \
|
|
-volid "ARCHIPELAGO" \
|
|
-J -R \
|
|
-c boot/syslinux/boot.cat \
|
|
-b boot/syslinux/isolinux.bin \
|
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
|
-isohybrid-mbr "$CUSTOM_DIR/boot/syslinux/isohdpfx.bin" \
|
|
"$CUSTOM_DIR" 2>&1 | grep -v "xorriso : UPDATE" || true
|
|
|
|
# Check if ISO was created
|
|
if [ ! -f "$OUTPUT_ISO" ]; then
|
|
echo "⚠️ xorriso failed, trying without isohybrid..."
|
|
xorriso -as mkisofs -o "$OUTPUT_ISO" \
|
|
-volid "ARCHIPELAGO" \
|
|
-J -R \
|
|
-c boot/syslinux/boot.cat \
|
|
-b boot/syslinux/isolinux.bin \
|
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
|
"$CUSTOM_DIR" 2>&1 | grep -v "xorriso : UPDATE"
|
|
fi
|
|
fi
|
|
else
|
|
# Fallback to hdiutil
|
|
hdiutil makehybrid -o "$OUTPUT_ISO" "$CUSTOM_DIR" \
|
|
-iso -joliet -default-volume-name "ARCHIPELAGO" || {
|
|
echo "❌ Failed to create ISO"
|
|
exit 1
|
|
}
|
|
fi
|
|
else
|
|
# On Linux, use genisoimage or xorriso
|
|
if command -v genisoimage >/dev/null 2>&1; then
|
|
genisoimage -o "$OUTPUT_ISO" \
|
|
-b boot/syslinux/isolinux.bin \
|
|
-c boot/syslinux/boot.cat \
|
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
|
-J -R -V "ARCHIPELAGO" \
|
|
"$CUSTOM_DIR"
|
|
elif command -v xorriso >/dev/null 2>&1; then
|
|
xorriso -as mkisofs -o "$OUTPUT_ISO" \
|
|
-b boot/syslinux/isolinux.bin \
|
|
-c boot/syslinux/boot.cat \
|
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
|
-J -R -V "ARCHIPELAGO" \
|
|
"$CUSTOM_DIR"
|
|
else
|
|
echo "❌ No ISO creation tool found (need genisoimage or xorriso)"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Make bootable (add isohybrid for USB boot)
|
|
if command -v isohybrid >/dev/null 2>&1 && [[ "$OSTYPE" != "darwin"* ]]; then
|
|
isohybrid "$OUTPUT_ISO"
|
|
fi
|
|
|
|
echo ""
|
|
echo "✅ ISO created successfully!"
|
|
echo ""
|
|
echo "📀 Output: $OUTPUT_ISO"
|
|
echo " Size: $(du -h "$OUTPUT_ISO" | cut -f1)"
|
|
echo ""
|
|
echo "📝 To create a bootable USB:"
|
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
echo " 1. Insert USB drive"
|
|
echo " 2. Find device: diskutil list"
|
|
echo " 3. Unmount: diskutil unmountDisk /dev/diskN"
|
|
echo " 4. Write: sudo dd if=$OUTPUT_ISO of=/dev/rdiskN bs=1m"
|
|
else
|
|
echo " sudo dd if=$OUTPUT_ISO of=/dev/sdX bs=4M status=progress"
|
|
fi
|
|
echo ""
|