#!/bin/bash # Main orchestrator script for Zero OS Alpine Initramfs Builder set -euo pipefail # Script directory and project root detection SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" # Source all libraries source "${SCRIPT_DIR}/lib/common.sh" source "${SCRIPT_DIR}/lib/docker.sh" source "${SCRIPT_DIR}/lib/alpine.sh" source "${SCRIPT_DIR}/lib/components.sh" source "${SCRIPT_DIR}/lib/initramfs.sh" source "${SCRIPT_DIR}/lib/kernel.sh" source "${SCRIPT_DIR}/lib/testing.sh" # Build configuration loaded from config/build.conf via common.sh # Environment variables can override config file values ALPINE_VERSION="${ALPINE_VERSION:-3.22}" KERNEL_VERSION="${KERNEL_VERSION:-6.12.44}" RUST_TARGET="${RUST_TARGET:-x86_64-unknown-linux-musl}" OPTIMIZATION_LEVEL="${OPTIMIZATION_LEVEL:-max}" # Directory configuration export INSTALL_DIR="${PROJECT_ROOT}/initramfs" export COMPONENTS_DIR="${PROJECT_ROOT}/components" export KERNEL_DIR="${PROJECT_ROOT}/kernel" export DIST_DIR="${PROJECT_ROOT}/dist" # Configuration files CONFIG_DIR="${PROJECT_ROOT}/config" PACKAGES_LIST="${CONFIG_DIR}/packages.list" SOURCES_CONF="${CONFIG_DIR}/sources.conf" MODULES_CONF="${CONFIG_DIR}/modules.conf" KERNEL_CONFIG="${CONFIG_DIR}/kernel.config" FIRMWARE_CONF="${CONFIG_DIR}/firmware.conf" ZINIT_CONFIG_DIR="${CONFIG_DIR}/zinit" # Build options USE_CONTAINER="${USE_CONTAINER:-auto}" CLEAN_BUILD="${CLEAN_BUILD:-false}" SKIP_TESTS="${SKIP_TESTS:-false}" KEEP_ARTIFACTS="${KEEP_ARTIFACTS:-false}" # Display usage information function show_usage() { cat << EOF Zero OS Alpine Initramfs Builder Usage: $0 [OPTIONS] Options: --clean Clean build (remove all artifacts first) --skip-tests Skip boot tests --keep-artifacts Keep build artifacts after completion --help Show this help message Environment Variables: ALPINE_VERSION Alpine Linux version (default: 3.22) KERNEL_VERSION Linux kernel version (default: 6.8.8) RUST_TARGET Rust compilation target (default: x86_64-unknown-linux-musl) OPTIMIZATION_LEVEL Optimization level: max|size|speed (default: max) DEBUG Enable debug output (default: 0) Examples: $0 # Basic build $0 --clean # Clean build $0 --container # Force container build DEBUG=1 $0 # Build with debug output EOF } # Parse command line arguments function parse_arguments() { while [[ $# -gt 0 ]]; do case $1 in --clean) CLEAN_BUILD="true" shift ;; --skip-tests) SKIP_TESTS="true" shift ;; --keep-artifacts) KEEP_ARTIFACTS="true" shift ;; --help|-h) show_usage exit 0 ;; *) log_error "Unknown option: $1" show_usage exit 1 ;; esac done } # Setup build environment function setup_build_environment() { section_header "Setting up build environment" log_info "Project root: ${PROJECT_ROOT}" log_info "Alpine version: ${ALPINE_VERSION}" log_info "Kernel version: ${KERNEL_VERSION}" log_info "Rust target: ${RUST_TARGET}" log_info "Optimization level: ${OPTIMIZATION_LEVEL}" # Create build directories safe_mkdir "$INSTALL_DIR" safe_mkdir "$COMPONENTS_DIR" safe_mkdir "$KERNEL_DIR" safe_mkdir "$DIST_DIR" # Check dependencies if ! check_dependencies; then log_error "Dependency check failed" return 1 fi # Verify configuration files exist verify_configuration_files log_info "Build environment setup complete" } # Verify all required configuration files exist function verify_configuration_files() { section_header "Verifying Configuration Files" local required_configs=( "$PACKAGES_LIST" "$SOURCES_CONF" "$MODULES_CONF" "$KERNEL_CONFIG" "$FIRMWARE_CONF" ) local missing_configs=() for config in "${required_configs[@]}"; do if [[ ! -f "$config" ]]; then missing_configs+=("$config") else log_info "✓ Configuration found: $(basename "$config")" fi done if [[ ${#missing_configs[@]} -gt 0 ]]; then log_error "Missing configuration files:" for config in "${missing_configs[@]}"; do log_error " - $config" done log_error "Run the setup script or create configuration files manually" return 1 fi # Check zinit configuration directory if [[ ! -d "$ZINIT_CONFIG_DIR" ]]; then log_error "zinit configuration directory not found: ${ZINIT_CONFIG_DIR}" return 1 fi log_info "All configuration files verified" } # Main build process function main_build_process() { section_header "Starting Zero OS Alpine Initramfs Build" local start_time=$(date +%s) # Phase 1: Extract Alpine miniroot alpine_extract_miniroot "$INSTALL_DIR" "$ALPINE_VERSION" # Phase 2: Configure Alpine system alpine_configure_repos "$INSTALL_DIR" "$ALPINE_VERSION" alpine_configure_system "$INSTALL_DIR" # Phase 3: Install Alpine packages (NO OpenRC) alpine_install_packages "$INSTALL_DIR" "$PACKAGES_LIST" # Phase 3.5: Install firmware packages for hardware support alpine_install_firmware "$INSTALL_DIR" "$FIRMWARE_CONF" # Phase 4: Build and install ThreeFold components components_parse_sources_conf "$SOURCES_CONF" "$COMPONENTS_DIR" # Phase 5: Verify component installation components_verify_installation # Phase 6: Setup zinit as init system initramfs_setup_zinit "$INSTALL_DIR" "$ZINIT_CONFIG_DIR" # Phase 7: Setup 2-stage module loading initramfs_setup_modules "$INSTALL_DIR" "$MODULES_CONF" "$KERNEL_VERSION" # Phase 8: Aggressive cleanup for size optimization alpine_aggressive_cleanup "$INSTALL_DIR" # Phase 9: Strip and UPX all binaries initramfs_strip_and_upx "$INSTALL_DIR" # Phase 10: Validate initramfs initramfs_validate "$INSTALL_DIR" # Phase 11: Create initramfs archive local initramfs_archive="${DIST_DIR}/initramfs.cpio.xz" initramfs_create_cpio "$INSTALL_DIR" "$initramfs_archive" # Phase 12: Test archive integrity initramfs_test_archive "$initramfs_archive" # Phase 13: Build kernel with embedded initramfs local kernel_output="${DIST_DIR}/vmlinuz.efi" kernel_build_with_initramfs "$KERNEL_CONFIG" "$initramfs_archive" "$kernel_output" # Phase 14: Run boot tests (unless skipped) if [[ "$SKIP_TESTS" != "true" ]]; then testing_run_all "$kernel_output" else log_info "Skipping boot tests as requested" fi # Calculate build time local end_time=$(date +%s) local build_time=$((end_time - start_time)) local build_minutes=$((build_time / 60)) local build_seconds=$((build_time % 60)) section_header "Build Complete" log_info "Build time: ${build_minutes}m ${build_seconds}s" log_info "Output files:" log_info " Kernel: ${kernel_output} ($(get_file_size "$kernel_output"))" log_info " Initramfs: ${initramfs_archive} ($(get_file_size "$initramfs_archive"))" } # Cleanup build artifacts function cleanup_build_artifacts() { if [[ "$KEEP_ARTIFACTS" != "true" ]]; then section_header "Cleaning Build Artifacts" components_cleanup "$COMPONENTS_DIR" "false" kernel_cleanup "$KERNEL_DIR" "false" log_info "Build artifacts cleaned" else log_info "Keeping build artifacts as requested" fi } # Main function function main() { # Parse command line arguments parse_arguments "$@" # Show banner echo "" echo "==================================================" echo "== ZERO-OS ALPINE INITRAMFS BUILDER ==" echo "== ThreeFold Edition ==" echo "==================================================" echo "" # Clean build if requested if [[ "$CLEAN_BUILD" == "true" ]]; then section_header "Clean Build Requested" "$SCRIPT_DIR/clean.sh" fi # Setup environment setup_build_environment # Always use container builds for consistency if in_container; then log_info "Already in container, proceeding with build" main_build_process elif command_exists "podman" || command_exists "docker"; then log_info "Starting container build" docker_detect_runtime docker_build_container # Pass through relevant arguments to container local container_args="" if [[ "$SKIP_TESTS" == "true" ]]; then container_args="$container_args --skip-tests" fi if [[ "$KEEP_ARTIFACTS" == "true" ]]; then container_args="$container_args --keep-artifacts" fi docker_run_build "./scripts/build.sh${container_args}" else log_error "Container runtime required (podman or docker)" log_error "Install with: apt-get install podman" return 1 fi # Cleanup if requested cleanup_build_artifacts section_header "Zero OS Build Complete" log_info "Ready to deploy Zero OS with Alpine Linux and zinit" } # Run main function with all arguments main "$@"