deb-bootc-image-builder-new/docs/simple-installer.md
2025-09-05 07:10:12 -07:00

13 KiB

Simple Bootc Installer

Overview

A minimal, web-based installer for bootc that follows the standard "curl | sh" pattern. This approach works with bootc's design rather than against it, providing a simple way to install bootc containers on bare metal.

Concept

# Simple one-liner installation
curl -fsSL https://install.bootc.dev | sh

# Or with specific container
curl -fsSL https://install.bootc.dev | sh -s -- quay.io/centos-bootc/centos-bootc:stream9

Architecture

1. Web-Based Installer Script

  • Single shell script hosted on a website
  • Self-contained - no external dependencies beyond curl
  • Interactive prompts for configuration
  • Validation of system requirements

2. Live CD Environment

  • Minimal live environment (Debian-based)
  • Pre-installed tools: podman, bootc, curl
  • Network connectivity for container pulling
  • No complex installer - just a shell script

3. Installation Flow

1. Boot live CD
2. Run: curl -fsSL https://install.bootc.dev | sh
3. Follow interactive prompts
4. Install completes automatically
5. Reboot into installed system

Implementation Plan

Phase 1: Core Installer Script (Week 1-2)

1.1 Basic Script Structure

#!/bin/bash
# bootc-installer.sh

set -euo pipefail

# Configuration
CONTAINER_URL="${1:-quay.io/centos-bootc/centos-bootc:stream9}"
TARGET_DEVICE=""
USERNAME=""
SSH_KEY=""

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Logging functions
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Main installer function
main() {
    log_info "Bootc Installer v1.0"
    log_info "Installing container: $CONTAINER_URL"
    
    check_requirements
    detect_target_device
    prompt_user_config
    install_bootc
    configure_system
    finalize_installation
}

1.2 System Requirements Check

check_requirements() {
    log_info "Checking system requirements..."
    
    # Check if running as root
    if [[ $EUID -ne 0 ]]; then
        log_error "This script must be run as root"
        exit 1
    fi
    
    # Check for required tools
    local required_tools=("podman" "bootc" "curl" "parted" "mkfs.ext4")
    for tool in "${required_tools[@]}"; do
        if ! command -v "$tool" &> /dev/null; then
            log_error "Required tool '$tool' not found"
            exit 1
        fi
    done
    
    # Check for internet connectivity
    if ! curl -s --connect-timeout 5 https://quay.io > /dev/null; then
        log_error "No internet connectivity. Required for container pulling."
        exit 1
    fi
    
    log_info "System requirements satisfied"
}

1.3 Device Detection and Selection

detect_target_device() {
    log_info "Detecting available storage devices..."
    
    # List available block devices
    local devices=($(lsblk -d -n -o NAME | grep -E '^[sv]d[a-z]$'))
    
    if [[ ${#devices[@]} -eq 0 ]]; then
        log_error "No suitable storage devices found"
        exit 1
    fi
    
    # Display available devices
    echo "Available storage devices:"
    for i in "${!devices[@]}"; do
        local device="/dev/${devices[$i]}"
        local size=$(lsblk -d -n -o SIZE "$device")
        local model=$(lsblk -d -n -o MODEL "$device" | head -1)
        echo "  $((i+1)). $device ($size) - $model"
    done
    
    # Prompt user for selection
    while true; do
        read -p "Select device number (1-${#devices[@]}): " choice
        if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le "${#devices[@]}" ]]; then
            TARGET_DEVICE="/dev/${devices[$((choice-1))]}"
            break
        else
            log_warn "Invalid selection. Please try again."
        fi
    done
    
    log_info "Selected device: $TARGET_DEVICE"
}

1.4 User Configuration Prompts

prompt_user_config() {
    log_info "Configuring user account..."
    
    # Get username
    while true; do
        read -p "Enter username for the system: " USERNAME
        if [[ -n "$USERNAME" ]] && [[ "$USERNAME" =~ ^[a-zA-Z0-9_-]+$ ]]; then
            break
        else
            log_warn "Invalid username. Use only letters, numbers, underscores, and hyphens."
        fi
    done
    
    # Get SSH key
    echo "Enter SSH public key for root access (optional):"
    echo "You can paste your public key here (it will be hidden):"
    read -s SSH_KEY
    echo
    
    log_info "User configuration complete"
}

Phase 2: Bootc Installation (Week 2-3)

2.1 Container Installation

install_bootc() {
    log_info "Installing bootc container..."
    
    # Pull the container image
    log_info "Pulling container image: $CONTAINER_URL"
    if ! podman pull "$CONTAINER_URL"; then
        log_error "Failed to pull container image"
        exit 1
    fi
    
    # Install bootc to disk
    log_info "Installing to device: $TARGET_DEVICE"
    if ! podman run \
        --rm \
        --privileged \
        --pid=host \
        -v /dev:/dev \
        -v /var/lib/containers:/var/lib/containers \
        --security-opt label=type:unconfined_t \
        "$CONTAINER_URL" \
        bootc install to-disk "$TARGET_DEVICE"; then
        log_error "Bootc installation failed"
        exit 1
    fi
    
    log_info "Bootc installation completed successfully"
}

2.2 Post-Install Configuration

configure_system() {
    log_info "Configuring installed system..."
    
    # Mount the installed system
    local mount_point="/mnt/bootc-install"
    mkdir -p "$mount_point"
    
    # Find the root partition
    local root_partition=$(find_root_partition)
    if [[ -z "$root_partition" ]]; then
        log_error "Could not find root partition"
        exit 1
    fi
    
    # Mount root partition
    if ! mount "$root_partition" "$mount_point"; then
        log_error "Failed to mount root partition"
        exit 1
    fi
    
    # Configure user account
    configure_user_account "$mount_point"
    
    # Configure SSH access
    if [[ -n "$SSH_KEY" ]]; then
        configure_ssh_access "$mount_point"
    fi
    
    # Unmount
    umount "$mount_point"
    
    log_info "System configuration completed"
}

find_root_partition() {
    # Look for the root partition on the target device
    local partitions=($(lsblk -n -o NAME "$TARGET_DEVICE" | tail -n +2))
    
    for partition in "${partitions[@]}"; do
        local part_path="/dev/$partition"
        # Check if this looks like a root partition
        if mount "$part_path" /mnt 2>/dev/null; then
            if [[ -d "/mnt/usr" ]] && [[ -d "/mnt/etc" ]]; then
                umount /mnt
                echo "$part_path"
                return
            fi
            umount /mnt
        fi
    done
}

configure_user_account() {
    local mount_point="$1"
    
    # Create user configuration for systemd-sysusers
    local sysusers_config="$mount_point/etc/sysusers.d/installer-user.conf"
    cat > "$sysusers_config" << EOF
u $USERNAME 1000 "$USERNAME" /home/$USERNAME
g $USERNAME 1000
m $USERNAME $USERNAME
EOF
    
    log_info "User account '$USERNAME' configured"
}

configure_ssh_access() {
    local mount_point="$1"
    
    # Create .ssh directory for root
    local ssh_dir="$mount_point/root/.ssh"
    mkdir -p "$ssh_dir"
    
    # Add SSH key
    echo "$SSH_KEY" > "$ssh_dir/authorized_keys"
    
    # Set proper permissions
    chmod 700 "$ssh_dir"
    chmod 600 "$ssh_dir/authorized_keys"
    
    log_info "SSH access configured for root"
}

Phase 3: Live CD Creation (Week 3-4)

3.1 Live CD Build Script

#!/bin/bash
# build-live-cd.sh

set -euo pipefail

# Configuration
LIVE_CD_NAME="bootc-installer-live"
LIVE_CD_VERSION="1.0"
OUTPUT_DIR="./live-cd-build"

# Create build directory
mkdir -p "$OUTPUT_DIR"
cd "$OUTPUT_DIR"

# Create live CD structure
mkdir -p {live,chroot}

# Install debootstrap
apt-get update
apt-get install -y debootstrap

# Bootstrap minimal Debian system
debootstrap --arch=amd64 trixie chroot/

# Install required packages
chroot chroot/ apt-get update
chroot chroot/ apt-get install -y \
    podman \
    bootc \
    curl \
    parted \
    e2fsprogs \
    grub-efi-amd64 \
    systemd \
    openssh-server \
    vim \
    nano

# Create installer script
cat > chroot/usr/local/bin/bootc-installer << 'EOF'
#!/bin/bash
# ... (installer script content)
EOF

chmod +x chroot/usr/local/bin/bootc-installer

# Create auto-run script
cat > chroot/etc/profile.d/bootc-installer.sh << 'EOF'
#!/bin/bash
if [[ -z "$BOOTC_INSTALLER_RUN" ]]; then
    export BOOTC_INSTALLER_RUN=1
    echo "Bootc Installer Live CD"
    echo "Run: bootc-installer"
    echo "Or: curl -fsSL https://install.bootc.dev | sh"
fi
EOF

# Build ISO
apt-get install -y live-build
lb config --binary-images iso-hybrid
lb build

3.2 Live CD Features

  • Minimal Debian Trixie base
  • Pre-installed tools: podman, bootc, curl, parted
  • Network configuration via DHCP
  • Auto-mount of installer script
  • GRUB2 bootloader with UEFI support

Phase 4: Web Hosting and Distribution (Week 4)

4.1 Web Server Setup

# nginx configuration for install.bootc.dev
server {
    listen 443 ssl;
    server_name install.bootc.dev;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        add_header Content-Type text/plain;
        add_header Cache-Control no-cache;
        return 200 "$(cat /var/www/install.bootc.dev/installer.sh)";
    }
    
    location /latest {
        return 302 https://install.bootc.dev/;
    }
}

4.2 Installer Script Hosting

# Simple script to serve the installer
#!/bin/bash
# serve-installer.sh

while true; do
    echo "Serving installer script..."
    cat installer.sh | nc -l 8080
done

Usage Examples

Basic Installation

# Boot from live CD, then:
curl -fsSL https://install.bootc.dev | sh

Install Specific Container

curl -fsSL https://install.bootc.dev | sh -s -- quay.io/myorg/my-bootc:latest

Install with Pre-configured Settings

# Set environment variables
export BOOTC_USERNAME="admin"
export BOOTC_SSH_KEY="ssh-rsa AAAAB3NzaC1yc2E..."
export BOOTC_DEVICE="/dev/sda"

curl -fsSL https://install.bootc.dev | sh

Advantages of This Approach

1. Simplicity

  • Single shell script
  • No complex dependencies
  • Easy to understand and modify

2. Compatibility

  • Works with bootc's design
  • No fighting against OSTree internals
  • Uses standard Linux tools

3. Flexibility

  • Easy to customize for different containers
  • Can be extended with additional features
  • Works with any bootc-compatible container

4. Reliability

  • Minimal failure points
  • Easy to debug and troubleshoot
  • Can be tested in virtual machines

5. User Experience

  • Familiar "curl | sh" pattern
  • Interactive prompts for configuration
  • Clear progress indicators

Implementation Timeline

  • Week 1-2: Core installer script development
  • Week 2-3: Bootc integration and testing
  • Week 3-4: Live CD creation and testing
  • Week 4: Web hosting and distribution setup

Testing Strategy

1. Virtual Machine Testing

  • Test with different container images
  • Test with various disk configurations
  • Test error handling and recovery

2. Hardware Testing

  • Test on different hardware configurations
  • Test with UEFI and legacy BIOS
  • Test with different storage devices

3. Network Testing

  • Test with different network configurations
  • Test with proxy/firewall environments
  • Test with slow/unreliable connections

Future Enhancements

1. Advanced Features

  • Multiple container selection
  • Custom partitioning options
  • Network configuration
  • Timezone and locale settings

2. Enterprise Features

  • Corporate registry integration
  • Signed installer verification
  • Audit logging
  • Remote management integration

3. UI Improvements

  • Web-based configuration interface
  • Progress bars and better feedback
  • Error recovery suggestions
  • Installation validation

Conclusion

This simple installer approach provides a practical, reliable way to install bootc containers while working with the tools rather than against them. The "curl | sh" pattern is familiar to users and the implementation is straightforward and maintainable.

The key advantages are:

  • Simplicity: Easy to understand and modify
  • Compatibility: Works with bootc's design
  • Reliability: Minimal failure points
  • Flexibility: Easy to extend and customize
  • User Experience: Familiar and intuitive

This approach can be implemented quickly and provides a solid foundation for more advanced features in the future.