553 lines
No EOL
22 KiB
Bash
Executable file
553 lines
No EOL
22 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# ParticleOS ISO Builder with mmdebstrap - HARDENED VERSION
|
|
# Builds a bootable ISO using mmdebstrap + apt-ostree integration
|
|
# Includes comprehensive error handling, safety checks, and hardening measures
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors
|
|
GREEN='\033[0;32m'
|
|
BLUE='\033[0;34m'
|
|
RED='\033[0;31m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
print_status() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
print_header() {
|
|
echo ""
|
|
echo -e "${BLUE}================================${NC}"
|
|
echo -e "${BLUE}$1${NC}"
|
|
echo -e "${BLUE}================================${NC}"
|
|
}
|
|
|
|
# Configuration
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_NAME="particleos"
|
|
VERSION="1.0.0"
|
|
BUILD_DIR="$SCRIPT_DIR/build"
|
|
CHROOT_DIR="$BUILD_DIR/chroot"
|
|
ISO_DIR="$BUILD_DIR/iso"
|
|
OUTPUT_DIR="$SCRIPT_DIR/output"
|
|
|
|
# Enhanced safety check: Ensure BUILD_DIR is within SCRIPT_DIR
|
|
if [[ ! "$BUILD_DIR" =~ ^"$SCRIPT_DIR" ]]; then
|
|
print_error "BUILD_DIR ($BUILD_DIR) is not within SCRIPT_DIR ($SCRIPT_DIR). Aborting for safety."
|
|
exit 1
|
|
fi
|
|
|
|
# Track mounted filesystems for cleanup
|
|
MOUNTED_FILESYSTEMS=()
|
|
|
|
# Enhanced cleanup function to unmount filesystems in reverse order
|
|
cleanup_mounts() {
|
|
print_status "Cleaning up mounted filesystems..."
|
|
# Iterate in reverse for safer unmounting
|
|
for (( i=${#MOUNTED_FILESYSTEMS[@]}-1; i>=0; i-- )); do
|
|
mount_point="${MOUNTED_FILESYSTEMS[i]}"
|
|
if mountpoint -q "$mount_point" 2>/dev/null; then
|
|
print_status "Unmounting $mount_point"
|
|
sudo umount "$mount_point" 2>/dev/null || print_warning "Failed to unmount $mount_point"
|
|
fi
|
|
done
|
|
MOUNTED_FILESYSTEMS=()
|
|
}
|
|
|
|
# Signal trap to ensure cleanup on script exit (handles Ctrl+C, errors, etc.)
|
|
trap cleanup_mounts EXIT INT TERM
|
|
|
|
# Enhanced safe mount function with error checking
|
|
safe_mount() {
|
|
local source="$1"
|
|
local target="$2"
|
|
local type="${3:-}"
|
|
|
|
# Validate mount points
|
|
if [[ ! -d "$target" ]]; then
|
|
print_error "Mount target directory does not exist: $target"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$type" ]; then
|
|
sudo mount -t "$type" "$source" "$target"
|
|
else
|
|
sudo mount --bind "$source" "$target"
|
|
fi
|
|
|
|
if [ $? -eq 0 ]; then
|
|
MOUNTED_FILESYSTEMS+=("$target")
|
|
print_status "Mounted $source to $target"
|
|
else
|
|
print_error "Failed to mount $source to $target"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Enhanced safe chroot function with error checking
|
|
safe_chroot() {
|
|
local command="$1"
|
|
local description="${2:-chroot command}"
|
|
|
|
print_status "Running: $description"
|
|
if sudo chroot "$CHROOT_DIR" bash -c "$command"; then
|
|
print_success "$description completed successfully"
|
|
else
|
|
print_error "$description failed"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Enhanced prerequisites check with better error handling
|
|
check_prerequisites() {
|
|
print_header "Phase 1: Check Prerequisites"
|
|
|
|
local missing_packages=()
|
|
|
|
# Check for build tools
|
|
for package in mmdebstrap squashfs-tools xorriso grub-pc-bin grub-efi-amd64-bin; do
|
|
if ! dpkg -s "$package" &>/dev/null; then
|
|
missing_packages+=("$package")
|
|
fi
|
|
done
|
|
|
|
# Enhanced ISOLINUX checks
|
|
if [ ! -f "/usr/lib/ISOLINUX/isohdpfx.bin" ]; then
|
|
print_error "ISOLINUX isohdpfx.bin not found. Please ensure 'isolinux' package is installed."
|
|
exit 1
|
|
fi
|
|
# Also check for isolinux.bin in standard locations
|
|
if [ ! -f "/usr/lib/syslinux/isolinux.bin" ] && [ ! -f "/usr/lib/ISOLINUX/isolinux.bin" ]; then
|
|
print_error "isolinux.bin not found. Please ensure 'isolinux' package is installed."
|
|
exit 1
|
|
fi
|
|
|
|
if [ ${#missing_packages[@]} -gt 0 ]; then
|
|
print_status "Installing missing packages: ${missing_packages[*]}"
|
|
sudo apt update || { print_error "Failed to update package lists"; exit 1; }
|
|
sudo apt install -y "${missing_packages[@]}" || { print_error "Failed to install missing packages"; exit 1; }
|
|
fi
|
|
|
|
# Enhanced disk space check (increased to 15GB for safety)
|
|
local available_space=$(df "$SCRIPT_DIR" | awk 'NR==2 {print $4}')
|
|
local required_space=$((15 * 1024 * 1024)) # 15GB in KB
|
|
|
|
if [ "$available_space" -lt "$required_space" ]; then
|
|
print_error "Insufficient disk space. Need at least 15GB free, have $(($available_space / 1024 / 1024))GB"
|
|
exit 1
|
|
fi
|
|
|
|
# Check network connectivity
|
|
if ! ping -c 1 archive.ubuntu.com &>/dev/null; then
|
|
print_error "Cannot reach Ubuntu archives. Check your internet connection."
|
|
exit 1
|
|
fi
|
|
|
|
if ! curl -s -I "https://git.raines.xyz/robojerk/apt-ostree/raw/branch/main/apt-ostree_0.1.0-1_amd64.deb" | head -n 1 | grep "HTTP/[12] [23].." > /dev/null; then
|
|
print_error "Cannot reach apt-ostree repository. Check your internet connection."
|
|
exit 1
|
|
fi
|
|
|
|
print_success "All prerequisites satisfied"
|
|
}
|
|
|
|
# Enhanced clean build environment with expanded safety checks
|
|
clean_build() {
|
|
print_header "Phase 2: Clean Build Environment"
|
|
|
|
if [ -d "$BUILD_DIR" ]; then
|
|
# Enhanced safety check: Expanded blacklist of critical directories
|
|
if [[ "$BUILD_DIR" == "/" ]] || [[ "$BUILD_DIR" == "/home" ]] || [[ "$BUILD_DIR" == "/opt" ]] || \
|
|
[[ "$BUILD_DIR" == "/usr" ]] || [[ "$BUILD_DIR" == "/var" ]] || [[ "$BUILD_DIR" == "/etc" ]] || \
|
|
[[ "$BUILD_DIR" == "/root" ]] || [[ "$BUILD_DIR" == "/tmp" ]] || [[ "$BUILD_DIR" == "/sbin" ]] || \
|
|
[[ "$BUILD_DIR" == "/bin" ]] || [[ "$BUILD_DIR" == "/lib" ]] || [[ "$BUILD_DIR" == "/lib64" ]]; then
|
|
print_error "BUILD_DIR ($BUILD_DIR) is a critical system directory. Aborting for safety."
|
|
exit 1
|
|
fi
|
|
|
|
print_status "Removing previous build directory: $BUILD_DIR..."
|
|
sudo rm -rf "$BUILD_DIR" || { print_error "Failed to remove previous build directory"; exit 1; }
|
|
fi
|
|
|
|
mkdir -p "$BUILD_DIR" "$CHROOT_DIR" "$ISO_DIR" "$OUTPUT_DIR" || { print_error "Failed to create build directories"; exit 1; }
|
|
print_success "Build environment cleaned"
|
|
}
|
|
|
|
# Enhanced base system creation using mmdebstrap
|
|
create_base_system() {
|
|
print_header "Phase 3: Create Base System with mmdebstrap"
|
|
|
|
print_status "Creating base Ubuntu system using mmdebstrap..."
|
|
|
|
# Enhanced base system with mmdebstrap
|
|
# Using --variant=minbase as it provides a minimal system more suitable for custom builds.
|
|
# Added 'locales' for proper locale generation and 'resolvconf' for DNS if needed.
|
|
if sudo mmdebstrap \
|
|
--architectures=amd64 \
|
|
--variant=minbase \
|
|
--include=systemd,systemd-sysv,dbus,curl,ca-certificates,gnupg,locales,resolvconf \
|
|
noble \
|
|
"$CHROOT_DIR" \
|
|
http://archive.ubuntu.com/ubuntu/; then
|
|
print_success "Base system created with mmdebstrap"
|
|
else
|
|
print_error "Failed to create base system with mmdebstrap"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Enhanced base system configuration
|
|
configure_base_system() {
|
|
print_header "Phase 4: Configure Base System"
|
|
|
|
print_status "Configuring base system..."
|
|
|
|
# Mount necessary filesystems
|
|
safe_mount "/dev" "$CHROOT_DIR/dev"
|
|
safe_mount "/run" "$CHROOT_DIR/run"
|
|
safe_mount "none" "$CHROOT_DIR/proc" "proc"
|
|
safe_mount "none" "$CHROOT_DIR/sys" "sysfs"
|
|
|
|
# Configure package sources
|
|
safe_chroot "echo 'deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse' > /etc/apt/sources.list" "Configure main sources"
|
|
safe_chroot "echo 'deb http://archive.ubuntu.com/ubuntu noble-updates main restricted universe multiverse' >> /etc/apt/sources.list" "Configure updates sources"
|
|
safe_chroot "echo 'deb http://security.ubuntu.com/ubuntu noble-security main restricted universe multiverse' >> /etc/apt/sources.list" "Configure security sources"
|
|
|
|
# Add Forgejo repository for apt-ostree and potentially other DEB packages (like Firefox if available)
|
|
print_status "Setting up Forgejo repository for apt-ostree and other packages..."
|
|
safe_chroot "mkdir -p /etc/apt/keyrings" "Create keyrings directory"
|
|
# Use -o /dev/null for curl output to stdout, pipe to gpg
|
|
safe_chroot "curl -fsSL https://git.raines.xyz/api/packages/robojerk/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/forgejo-robojerk.gpg" "Download and import Forgejo GPG key"
|
|
safe_chroot "echo 'deb [signed-by=/etc/apt/keyrings/forgejo-robojerk.gpg] https://git.raines.xyz/api/packages/robojerk/debian noble main' > /etc/apt/sources.list.d/forgejo.list" "Add Forgejo repository"
|
|
|
|
# Update package lists
|
|
safe_chroot "apt update" "Update package lists"
|
|
|
|
# Enhanced package installation with ostree and bootc
|
|
# Including 'ostree' and 'bootc' as requested
|
|
# If a DEB for Firefox exists in any enabled repo, it will be preferred over Snap due to preferences below.
|
|
safe_chroot "DEBIAN_FRONTEND=noninteractive apt install -y \
|
|
kubuntu-desktop plasma-desktop plasma-workspace kde-plasma-desktop sddm \
|
|
ostree bootc flatpak \
|
|
network-manager plasma-nm \
|
|
openssh-server \
|
|
curl wget vim nano htop neofetch tree \
|
|
firefox \
|
|
pulseaudio pulseaudio-utils \
|
|
fonts-ubuntu fonts-noto \
|
|
build-essential git \
|
|
live-boot live-config casper" "Install desktop and core live packages"
|
|
|
|
# Download and install apt-ostree from custom repository (assuming it's not in the Forgejo apt repo directly)
|
|
print_status "Installing apt-ostree from custom repository directly..."
|
|
safe_chroot "timeout 60 wget -O /tmp/apt-ostree.deb 'https://git.raines.xyz/robojerk/apt-ostree/raw/branch/main/apt-ostree_0.1.0-1_amd64.deb'" "Download apt-ostree"
|
|
safe_chroot "dpkg -i /tmp/apt-ostree.deb || apt install -f -y" "Install apt-ostree and fix dependencies"
|
|
safe_chroot "rm -f /tmp/apt-ostree.deb" "Clean up apt-ostree download"
|
|
|
|
# Enhanced snap removal and blocking
|
|
print_status "Removing snapd and setting APT preferences to block snaps..."
|
|
safe_chroot "DEBIAN_FRONTEND=noninteractive apt purge -y snapd ubuntu-advantage-tools update-notifier update-manager unattended-upgrades" "Purge unwanted packages"
|
|
safe_chroot "apt autoremove -y" "Autoremove orphaned packages"
|
|
safe_chroot "apt-mark hold snapd" "Hold snapd"
|
|
# Create an APT preference file to strongly discourage snapd and enforce non-snap Firefox
|
|
safe_chroot "echo 'Package: snapd' > /etc/apt/preferences.d/nosnap.pref" "Create nosnap.pref"
|
|
safe_chroot "echo 'Pin: release *' >> /etc/apt/preferences.d/nosnap.pref" "Set nosnap.pref pin release"
|
|
safe_chroot "echo 'Pin-Priority: -1' >> /etc/apt/preferences.d/nosnap.pref" "Set nosnap.pref pin priority"
|
|
safe_chroot "echo 'Package: firefox' >> /etc/apt/preferences.d/nosnap.pref" "Add firefox to nosnap.pref"
|
|
safe_chroot "echo 'Pin: release o=Ubuntu' >> /etc/apt/preferences.d/nosnap.pref" "Pin Firefox to Ubuntu archive"
|
|
safe_chroot "echo 'Pin-Priority: 1000' >> /etc/apt/preferences.d/nosnap.pref" "Give high priority to APT Firefox"
|
|
|
|
# Enhanced system configuration
|
|
safe_chroot "echo 'particleos' > /etc/hostname" "Set hostname"
|
|
safe_chroot "echo '127.0.0.1 localhost' >> /etc/hosts" "Add localhost to hosts" # More standard
|
|
safe_chroot "echo '127.0.1.1 particleos.local particleos' >> /etc/hosts" "Add hostname to hosts"
|
|
safe_chroot "ln -sf /usr/share/zoneinfo/UTC /etc/localtime" "Set timezone to UTC"
|
|
safe_chroot "locale-gen en_US.UTF-8" "Generate locale" # Important for desktop
|
|
safe_chroot "update-locale LANG=en_US.UTF-8" "Set default locale"
|
|
|
|
# Enhanced user creation
|
|
print_status "Creating user 'particle'..."
|
|
safe_chroot "useradd -m -s /bin/bash particle" "Create particle user"
|
|
safe_chroot "echo 'particle:particle' | chpasswd" "Set particle password"
|
|
safe_chroot "usermod -aG sudo particle" "Add particle to sudo group"
|
|
safe_chroot "echo 'particle ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/particle" "Allow particle sudo without password (for live system)"
|
|
safe_chroot "chmod 0440 /etc/sudoers.d/particle" "Set correct permissions for sudoers file"
|
|
|
|
# Enhanced service configuration
|
|
print_status "Enabling essential services..."
|
|
safe_chroot "systemctl enable sddm NetworkManager ssh" "Enable key services" # Removed systemd-networkd, systemd-resolved if NetworkManager is used for DNS.
|
|
safe_chroot "systemctl disable apt-daily.timer apt-daily-upgrade.timer" "Disable daily apt timers for live system"
|
|
|
|
# Enhanced apt-ostree configuration
|
|
print_status "Configuring apt-ostree..."
|
|
safe_chroot "mkdir -p /etc/apt-ostree" "Create apt-ostree config directory"
|
|
safe_chroot "echo 'ref: particleos/desktop/1.0.0' > /etc/apt-ostree/ref" "Configure apt-ostree ref"
|
|
# Additional OSTree setup (initial commit, etc.) would typically happen here if building a committed image
|
|
# For a live ISO, apt-ostree mostly provides its tools.
|
|
|
|
# Enhanced cleanup
|
|
print_status "Cleaning APT caches in chroot..."
|
|
safe_chroot "apt clean" "Clean apt cache"
|
|
safe_chroot "rm -rf /var/lib/apt/lists/*" "Remove apt lists"
|
|
safe_chroot "rm -rf /tmp/*" "Clean /tmp"
|
|
|
|
print_success "Base system configured"
|
|
}
|
|
|
|
# Enhanced live filesystem creation
|
|
create_live_fs() {
|
|
print_header "Phase 5: Create Live Filesystem"
|
|
|
|
print_status "Creating live filesystem structure..."
|
|
|
|
# Create ISO directory structure
|
|
# Adding EFI/BOOT and boot/grub for UEFI/BIOS
|
|
mkdir -p "$ISO_DIR"/{casper,boot/grub,EFI/BOOT,isolinux} || { print_error "Failed to create ISO directories"; exit 1; }
|
|
|
|
# Enhanced kernel and initrd copying
|
|
print_status "Copying kernel and initramfs..."
|
|
# Find the latest kernel and initrd
|
|
local kernel_version=$(basename "$CHROOT_DIR"/boot/vmlinuz-* | sort -V | tail -n 1 | sed 's/vmlinuz-//')
|
|
local initrd_version=$(basename "$CHROOT_DIR"/boot/initrd.img-* | sort -V | tail -n 1 | sed 's/initrd.img-//')
|
|
|
|
if [ -z "$kernel_version" ] || [ -z "$initrd_version" ]; then
|
|
print_error "Could not find kernel or initrd in chroot/boot."
|
|
exit 1
|
|
fi
|
|
|
|
cp "$CHROOT_DIR/boot/vmlinuz-$kernel_version" "$ISO_DIR/casper/vmlinuz" || { print_error "Failed to copy kernel"; exit 1; }
|
|
cp "$CHROOT_DIR/boot/initrd.img-$initrd_version" "$ISO_DIR/casper/initrd" || { print_error "Failed to copy initrd"; exit 1; }
|
|
print_success "Kernel and initramfs copied."
|
|
|
|
# Enhanced filesystem manifest creation
|
|
print_status "Creating filesystem manifest..."
|
|
safe_chroot "dpkg-query -W --showformat='\${Package} \${Version}\n' > /filesystem.manifest" "Create filesystem manifest"
|
|
cp "$CHROOT_DIR/filesystem.manifest" "$ISO_DIR/casper/filesystem.manifest" || { print_error "Failed to copy filesystem.manifest"; exit 1; }
|
|
safe_chroot "rm /filesystem.manifest" "Clean up manifest in chroot" # Remove temp file in chroot
|
|
|
|
# Enhanced filesystem size calculation
|
|
print_status "Calculating filesystem size..."
|
|
sudo du -sx --block-size=1 "$CHROOT_DIR" | cut -f1 > "$ISO_DIR/casper/filesystem.size" || { print_error "Failed to create filesystem.size"; exit 1; }
|
|
print_success "Filesystem size calculated."
|
|
|
|
# Enhanced squashfs creation
|
|
print_status "Creating squashfs filesystem from chroot..."
|
|
# IMPORTANT: Unmount internal chroot mounts before mksquashfs for cleanest image
|
|
cleanup_mounts # Call the cleanup function here to unmount /dev, /run, /proc, /sys from chroot
|
|
|
|
if sudo mksquashfs "$CHROOT_DIR" "$ISO_DIR/casper/filesystem.squashfs" -comp xz -e boot; then
|
|
print_success "Squashfs created."
|
|
else
|
|
print_error "Failed to create squashfs."
|
|
exit 1
|
|
fi
|
|
print_status "Re-mounting filesystems in chroot for any subsequent operations (though none currently follow in this script)."
|
|
# Re-mount for consistency, though currently nothing follows. The EXIT trap will handle final unmount.
|
|
safe_mount "/dev" "$CHROOT_DIR/dev"
|
|
safe_mount "/run" "$CHROOT_DIR/run"
|
|
safe_mount "none" "$CHROOT_DIR/proc" "proc"
|
|
safe_mount "none" "$CHROOT_DIR/sys" "sysfs"
|
|
}
|
|
|
|
# Enhanced boot configuration setup
|
|
setup_boot() {
|
|
print_header "Phase 6: Setup Boot Configuration"
|
|
|
|
print_status "Setting up boot configuration..."
|
|
|
|
# Enhanced GRUB configuration (for UEFI)
|
|
cat > "$ISO_DIR/boot/grub/grub.cfg" << 'EOF'
|
|
set timeout=10
|
|
set default=0
|
|
|
|
menuentry "Try ParticleOS without installing" {
|
|
linux /casper/vmlinuz boot=casper quiet splash ---
|
|
initrd /casper/initrd
|
|
}
|
|
|
|
menuentry "Install ParticleOS" {
|
|
linux /casper/vmlinuz boot=casper quiet splash ---
|
|
initrd /casper/initrd
|
|
}
|
|
|
|
menuentry "Check disc for defects" {
|
|
linux /casper/vmlinuz boot=casper integrity-check quiet splash ---
|
|
initrd /casper/initrd
|
|
}
|
|
EOF
|
|
print_success "GRUB configuration created."
|
|
|
|
# Enhanced ISOLINUX configuration (for BIOS)
|
|
cat > "$ISO_DIR/isolinux/isolinux.cfg" << 'EOF'
|
|
DEFAULT live
|
|
TIMEOUT 300
|
|
PROMPT 1
|
|
|
|
LABEL live
|
|
MENU LABEL Try ParticleOS without installing
|
|
KERNEL /casper/vmlinuz
|
|
APPEND boot=casper initrd=/casper/initrd quiet splash ---
|
|
|
|
LABEL live-install
|
|
MENU LABEL Install ParticleOS
|
|
KERNEL /casper/vmlinuz
|
|
APPEND boot=casper initrd=/casper/initrd quiet splash ---
|
|
|
|
LABEL check
|
|
MENU LABEL Check disc for defects
|
|
KERNEL /casper/vmlinuz
|
|
APPEND boot=casper integrity-check initrd=/casper/initrd quiet splash ---
|
|
EOF
|
|
print_success "ISOLINUX configuration created."
|
|
|
|
# Enhanced ISOLINUX boot files copying
|
|
print_status "Copying ISOLINUX boot files..."
|
|
# Determine correct isolinux path (can vary by distro/version)
|
|
ISOLINUX_BIN_PATH=""
|
|
if [ -f "/usr/lib/syslinux/isolinux.bin" ]; then
|
|
ISOLINUX_BIN_PATH="/usr/lib/syslinux"
|
|
elif [ -f "/usr/lib/ISOLINUX/isolinux.bin" ]; then
|
|
ISOLINUX_BIN_PATH="/usr/lib/ISOLINUX"
|
|
fi
|
|
|
|
if [ -z "$ISOLINUX_BIN_PATH" ]; then
|
|
print_error "isolinux.bin path not found. ISO creation might fail."
|
|
exit 1
|
|
fi
|
|
|
|
cp "$ISOLINUX_BIN_PATH/isolinux.bin" "$ISO_DIR/isolinux/" || { print_error "Failed to copy isolinux.bin"; exit 1; }
|
|
print_success "ISOLINUX boot files copied."
|
|
|
|
# Enhanced EFI boot image creation (for UEFI)
|
|
# This assumes grub-efi-amd64-bin provides the necessary files to create efi.img.
|
|
# A robust solution might involve grub-mkimage. For a simple live ISO, this is often sufficient.
|
|
print_status "Creating EFI boot image..."
|
|
GRUB_EFI_DIR="/usr/lib/grub/efi-amd64" # Standard path for grub-efi-amd64-bin
|
|
if [ ! -d "$GRUB_EFI_DIR" ]; then
|
|
print_error "GRUB EFI directory not found at $GRUB_EFI_DIR. Cannot create EFI boot image."
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "$ISO_DIR/EFI/BOOT" || { print_error "Failed to create EFI/BOOT directory"; exit 1; }
|
|
# Copy essential EFI files for direct boot (e.g., used by some VMs/UEFI firmwares)
|
|
cp "$GRUB_EFI_DIR/grubx64.efi" "$ISO_DIR/EFI/BOOT/bootx64.efi" || { print_error "Failed to copy grubx64.efi"; exit 1; }
|
|
|
|
# Create the EFI grub.cfg for the live system
|
|
cat > "$ISO_DIR/EFI/BOOT/grub.cfg" << 'EOF'
|
|
search --set=root --file /casper/vmlinuz
|
|
set timeout=10
|
|
set default=0
|
|
|
|
menuentry "Try ParticleOS without installing" {
|
|
linux ($root)/casper/vmlinuz boot=casper quiet splash ---
|
|
initrd ($root)/casper/initrd
|
|
}
|
|
|
|
menuentry "Install ParticleOS" {
|
|
linux ($root)/casper/vmlinuz boot=casper quiet splash ---
|
|
initrd ($root)/casper/initrd
|
|
}
|
|
|
|
menuentry "Check disc for defects" {
|
|
linux ($root)/casper/vmlinuz boot=casper integrity-check quiet splash ---
|
|
initrd ($root)/casper/initrd
|
|
}
|
|
EOF
|
|
print_success "EFI boot configuration created."
|
|
}
|
|
|
|
# Enhanced ISO creation
|
|
create_iso() {
|
|
print_header "Phase 7: Create ISO" # Updated phase number
|
|
|
|
print_status "Creating bootable ISO using xorriso..."
|
|
|
|
# Enhanced check for isolinux.bin location for xorriso
|
|
local isolinux_bin=""
|
|
if [ -f "/usr/lib/syslinux/isolinux.bin" ]; then
|
|
isolinux_bin="/usr/lib/syslinux/isolinux.bin"
|
|
elif [ -f "/usr/lib/ISOLINUX/isolinux.bin" ]; then
|
|
isolinux_bin="/usr/lib/ISOLINUX/isolinux.bin"
|
|
fi
|
|
|
|
if [ -z "$isolinux_bin" ]; then
|
|
print_error "Cannot find isolinux.bin for xorriso. Aborting ISO creation."
|
|
exit 1
|
|
fi
|
|
|
|
# Enhanced ISO creation using xorriso
|
|
# -part_like_isohybrid: Better for modern systems
|
|
if sudo xorriso -as mkisofs \
|
|
-o "$OUTPUT_DIR/${PROJECT_NAME}-${VERSION}.iso" \
|
|
-J -joliet-long \
|
|
-r -V "ParticleOS ${VERSION}" \
|
|
-b isolinux/isolinux.bin \
|
|
-boot-load-size 4 -boot-info-table \
|
|
-no-emul-boot -eltorito-alt-boot \
|
|
-e EFI/BOOT/bootx64.efi -no-emul-boot \
|
|
-isohybrid-mbr "$isolinux_bin" \
|
|
-partition_offset 16 \
|
|
-part_like_isohybrid \
|
|
"$ISO_DIR"; then
|
|
print_success "ISO created successfully: $OUTPUT_DIR/${PROJECT_NAME}-${VERSION}.iso"
|
|
else
|
|
print_error "Failed to create ISO"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Enhanced main build process
|
|
main() {
|
|
echo "🚀 ParticleOS ISO Builder (mmdebstrap) - HARDENED VERSION"
|
|
echo "=================================================="
|
|
echo "Project: $PROJECT_NAME"
|
|
echo "Version: $VERSION"
|
|
echo "Build Directory: $BUILD_DIR"
|
|
echo "Tool: mmdebstrap"
|
|
echo ""
|
|
echo "🛡️ This build includes enhanced safety measures:"
|
|
echo " - Expanded directory blacklist"
|
|
echo " - Enhanced error handling"
|
|
echo " - Better mount/unmount management"
|
|
echo " - Comprehensive ISOLINUX support"
|
|
echo " - Robust cleanup procedures"
|
|
echo ""
|
|
|
|
# Run enhanced build phases
|
|
check_prerequisites
|
|
clean_build
|
|
create_base_system
|
|
configure_base_system
|
|
create_live_fs # New phase for clarity
|
|
setup_boot # New phase for clarity
|
|
create_iso
|
|
|
|
print_header "Build Complete!"
|
|
echo ""
|
|
echo "🎉 ParticleOS ISO built successfully!"
|
|
echo "📁 Location: $OUTPUT_DIR/${PROJECT_NAME}-${VERSION}.iso"
|
|
echo ""
|
|
echo "🧪 Test the ISO:"
|
|
echo " qemu-system-x86_64 -m 4G -enable-kvm \\"
|
|
echo " -cdrom $OUTPUT_DIR/${PROJECT_NAME}-${VERSION}.iso \\"
|
|
echo " -boot d"
|
|
echo ""
|
|
echo "🛡️ Enhanced safety measures applied!"
|
|
}
|
|
|
|
# Run main function
|
|
main "$@" |