#!/bin/bash # Exit on error set -e ################################################################################################################## # Custom Arch ISO Builder Script (Linux Version) ################################################################################################################## # Get absolute path of script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Setting general parameters buildFolder="$SCRIPT_DIR/build" outFolder="$SCRIPT_DIR/out" dockerImageName="arch-iso-builder-base" dockerContainerName="arch-iso-builder-base-container" # Get current user ID and group ID HOST_UID=$(id -u) HOST_GID=$(id -g) # Check if Docker is installed if ! command -v docker &> /dev/null; then echo "Docker is not installed. Installing Docker..." sudo pacman -S --noconfirm docker # Start and enable Docker service echo "Starting Docker service..." sudo systemctl start docker sudo systemctl enable docker # Add current user to docker group to avoid using sudo echo "Adding current user to docker group..." sudo usermod -aG docker $(whoami) echo "Docker installation completed. You may need to log out and back in for group changes to take effect." echo "Continuing with Docker as root for now..." fi # Check if Docker daemon is running if ! docker info &> /dev/null; then echo "Docker daemon is not running. Starting Docker service..." sudo systemctl start docker # Wait for Docker daemon to start (with timeout) echo "Waiting for Docker daemon to start..." max_attempts=10 attempt=1 while ! docker info &> /dev/null; do if [ $attempt -gt $max_attempts ]; then echo "Error: Docker daemon failed to start after $max_attempts attempts." echo "Please try starting it manually with: sudo systemctl start docker" exit 1 fi echo "Attempt $attempt/$max_attempts: Docker daemon not ready yet. Waiting 2 seconds..." sleep 2 attempt=$((attempt+1)) done echo "Docker daemon is now running." fi echo "################################################################" echo "Build folder: $buildFolder" echo "Out folder : $outFolder" echo "################################################################" echo "Building in Docker - using all CPU cores" echo "################################################################" # Create Docker image if it doesn't exist if ! docker image inspect "$dockerImageName" &>/dev/null; then echo "Creating Docker image: $dockerImageName..." # Create temporary Dockerfile cat > "$SCRIPT_DIR/Dockerfile" << EOF FROM archlinux:latest # Update system and install required packages RUN pacman -Syu --noconfirm && \ pacman -S --noconfirm archiso base-devel git sudo # Create a build user with same UID as host user RUN useradd -m -G wheel -u $HOST_UID builder && \ echo '%wheel ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers # Set up working directory WORKDIR /build # Keep container running for reuse CMD ["/bin/bash"] EOF # Build Docker image docker build -t "$dockerImageName" -f "$SCRIPT_DIR/Dockerfile" "$SCRIPT_DIR" # Remove temporary Dockerfile rm "$SCRIPT_DIR/Dockerfile" fi # Check if container exists if docker container inspect "$dockerContainerName" &>/dev/null; then # Container exists, check if it's running if [ "$(docker container inspect -f '{{.State.Running}}' "$dockerContainerName")" != "true" ]; then echo "Starting existing Docker container: $dockerContainerName..." docker start "$dockerContainerName" else echo "Using existing running Docker container: $dockerContainerName..." fi else # Container doesn't exist, create and start it echo "Creating and starting Docker container: $dockerContainerName..." docker run -d \ --name "$dockerContainerName" \ --privileged \ --cpus="$(nproc)" \ -v "$SCRIPT_DIR:/build" \ "$dockerImageName" \ tail -f /dev/null fi # Create required directories mkdir -p "$buildFolder" "$outFolder" # Run the build process inside Docker echo "Building ISO in Docker container..." docker exec -it "$dockerContainerName" bash -c " cd /build && \ # Make mkarchiso verbose sudo sed -i 's/quiet=\"y\"/quiet=\"n\"/g' /usr/bin/mkarchiso && \ # Clean build environment [ -d \"/build/build\" ] && sudo rm -rf \"/build/build\" && \ mkdir -p \"/build/build\" && \ # Copy releng folder cp -r \"/build/releng\" \"/build/build/\" && \ # Copy pkgs folder (if it exists), then generate repo db if [ -d \"/build/pkgs\" ]; then cp -r \"/build/pkgs\" \"/build/build/\" && \ echo \"Copied pkgs folder to build directory\" && \ if ls /build/build/pkgs/*.pkg.tar.* 1>/dev/null 2>&1; then echo \"Generating local repository database (repo-add custom.db.tar.gz) ...\" && \ sudo repo-add /build/build/pkgs/custom.db.tar.gz /build/build/pkgs/*.pkg.tar.* && \ echo \"Local repo database created.\" else echo \"No .pkg.tar.* files found in pkgs. Skipping repo-add.\" fi else echo \"Warning: pkgs folder not found in \$SCRIPT_DIR\" fi && \ # Create output directory mkdir -p \"/build/out\" && \ # Build ISO cd \"/build/build/releng\" && \ sudo mkarchiso -v -w \"/build/build\" -o \"/build/out\" \"\$PWD\" && \ # Save package list rename=\$(date +%Y-%m-%d) && \ if [ -f \"/build/build/iso/arch/pkglist.x86_64.txt\" ]; then sudo cp \"/build/build/iso/arch/pkglist.x86_64.txt\" \"/build/out/archlinux-\$rename-pkglist.txt\" fi && \ # Clean build environment sudo rm -rf \"/build/build\" && \ # Fix permissions on out folder sudo chown -R $HOST_UID:$HOST_GID \"/build/out\" " echo "################################################################" echo "DONE" echo "Check your out folder: $outFolder" echo "################################################################"