debian-bootc-simple/create-bootc-image.sh
2025-08-21 07:31:52 -07:00

350 lines
8.8 KiB
Bash
Executable file

#!/bin/bash
# Main orchestration script for creating bootc images
# This script uses modular components to create bootable images from containers or chroot
set -e
# Source configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/config/defaults.sh"
# Source all modules
source "$SCRIPT_DIR/modules/common.sh"
source "$SCRIPT_DIR/modules/disk.sh"
source "$SCRIPT_DIR/modules/filesystem.sh"
source "$SCRIPT_DIR/modules/bootloader.sh"
source "$SCRIPT_DIR/modules/formats.sh"
source "$SCRIPT_DIR/modules/chroot.sh"
# Mark common as loaded
COMMON_LOADED=true
# Main workflow functions
create_container_image() {
log_info "Creating container image..."
if [ "$USE_APT_CACHER" = "true" ]; then
log_info "Building with apt-cacher-ng support..."
if command -v ./build-with-cache.sh >/dev/null 2>&1; then
./build-with-cache.sh
else
log_warn "build-with-cache.sh not found, falling back to direct build"
podman build -t "$CONTAINER_IMAGE" -f debian_bootc_dockerfile.txt .
fi
else
log_info "Building container directly..."
podman build -t "$CONTAINER_IMAGE" -f debian_bootc_dockerfile.txt .
fi
log_info "Container image created: $CONTAINER_IMAGE"
}
create_chroot_image() {
log_info "Creating chroot-based image..."
# Create chroot environment
create_chroot_environment
# Install packages
install_chroot_packages
# Initialize OSTree
init_ostree_repository
create_ostree_commit
deploy_ostree_system
# Configure bootloader
configure_chroot_bootloader
log_info "Chroot-based image created"
}
create_disk_image() {
log_info "Creating disk image..."
# Create and partition disk
create_disk_image_work
create_essential_directories
log_info "Disk image created and partitioned"
}
extract_filesystem() {
log_info "Extracting filesystem..."
if [ "$BUILD_TYPE" = "container" ]; then
# Extract from container
extract_container_filesystem
else
# Copy from chroot
copy_chroot_filesystem
fi
# Fix permissions
fix_file_permissions
# Verify integrity
if [ "$VERIFY_FILESYSTEM" = "true" ]; then
verify_filesystem_integrity
fi
log_info "Filesystem extraction completed"
}
install_bootloader() {
log_info "Installing bootloader..."
if [ "$BOOTLOADER_TYPE" = "grub" ]; then
install_grub_bootloader
else
install_systemd_boot
fi
# Verify bootloader
if [ "$VERIFY_BOOTLOADER" = "true" ]; then
verify_bootloader
fi
log_info "Bootloader installation completed"
}
convert_formats() {
log_info "Converting to output formats..."
case "$OUTPUT_FORMATS" in
"qcow2")
convert_to_qcow2
;;
"iso")
convert_to_iso
;;
"img")
convert_to_img
;;
"vmdk")
convert_to_vmdk
;;
"vdi")
convert_to_vdi
;;
"all")
convert_to_all_formats
;;
*)
log_error "Unknown output format: $OUTPUT_FORMATS"
exit 1
;;
esac
log_info "Format conversion completed"
}
cleanup_work() {
log_info "Cleaning up work environment..."
if [ "$CLEANUP_WORK_DIR" = "true" ]; then
cleanup
fi
if [ "$BUILD_TYPE" = "chroot" ]; then
cleanup_chroot
fi
log_info "Cleanup completed"
}
# Main execution function
main() {
log_info "Starting bootc image creation..."
# Print configuration
print_config
# Validate configuration
if ! validate_config; then
exit 1
fi
# Setup cleanup
setup_cleanup
# Create output directory
create_output_dir
# Create work directory
create_work_dir
# Check prerequisites
check_prerequisites
# Create source image (container or chroot)
if [ "$BUILD_TYPE" = "container" ]; then
create_container_image
else
create_chroot_image
fi
# Create disk image
create_disk_image
# Extract filesystem
extract_filesystem
# Get the loop device from the disk module
# The disk module should have set loop_dev, but we need to ensure it's available
if [ -z "$loop_dev" ]; then
# Try to find the loop device by looking at the raw image
if [ -f "$OUTPUT_DIR/debian-bootc.raw" ]; then
loop_dev=$(sudo losetup --find --show "$OUTPUT_DIR/debian-bootc.raw")
log_info "Found loop device: $loop_dev"
else
log_error "Cannot find loop device or raw image"
exit 1
fi
fi
# Install bootloader
install_bootloader
# Convert to output formats
convert_formats
# Verify final image
if [ "$VERIFY_IMAGE" = "true" ]; then
verify_disk_integrity
fi
# Show final results
show_format_info
# Cleanup
cleanup_work
log_info "Bootc image creation completed successfully!"
log_info "Output directory: $OUTPUT_DIR"
}
# Show usage
show_usage() {
cat << EOF
Usage: $0 [OPTIONS]
Create a bootable bootc image from container or chroot.
OPTIONS:
-t, --type TYPE Build type: container or chroot (default: container)
-f, --format FORMAT Output format: qcow2, iso, img, vmdk, vdi, all (default: qcow2)
-s, --size SIZE Image size in GB (default: 10)
-o, --output DIR Output directory (default: ./output)
-c, --container IMAGE Container image name (default: localhost/debian-bootc:ostree-transformed-v2)
-b, --bootloader TYPE Bootloader type: grub or systemd-boot (default: grub)
-a, --arch ARCH Target architecture (default: amd64)
-r, --release RELEASE Debian release: trixie, forky, sid (default: trixie)
-u, --user USER Default username (default: debian)
-p, --password PASS Default password (default: debian123)
-n, --no-cache Disable apt-cacher-ng
-v, --verbose Enable verbose output
-h, --help Show this help message
EXAMPLES:
# Create QCOW2 image from container
$0 -t container -f qcow2
# Create ISO image from chroot
$0 -t chroot -f iso -s 20
# Create all formats from container
$0 -t container -f all -o ./my-images
# Custom configuration
BUILD_TYPE=chroot OUTPUT_FORMATS=iso $0
CONFIGURATION:
Environment variables can be used to override defaults:
- BUILD_TYPE: container or chroot
- OUTPUT_FORMATS: qcow2, iso, img, vmdk, vdi, all
- IMAGE_SIZE_GB: Image size in gigabytes
- OUTPUT_DIR: Output directory
- CONTAINER_IMAGE: Container image name
- BOOTLOADER_TYPE: grub or systemd-boot
- TARGET_ARCH: Target architecture
- TARGET_DEBIAN_RELEASE: Debian release
- DEFAULT_USER: Default username
- DEFAULT_PASSWORD: Default password
- USE_APT_CACHER: Enable/disable apt-cacher-ng
EOF
}
# Parse command line arguments
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
-t|--type)
BUILD_TYPE="$2"
shift 2
;;
-f|--format)
OUTPUT_FORMATS="$2"
shift 2
;;
-s|--size)
IMAGE_SIZE_GB="$2"
shift 2
;;
-o|--output)
OUTPUT_DIR="$2"
shift 2
;;
-c|--container)
CONTAINER_IMAGE="$2"
shift 2
;;
-b|--bootloader)
BOOTLOADER_TYPE="$2"
shift 2
;;
-a|--arch)
TARGET_ARCH="$2"
shift 2
;;
-r|--release)
DEBIAN_RELEASE="$2"
shift 2
;;
-u|--user)
DEFAULT_USER="$2"
shift 2
;;
-p|--password)
DEFAULT_PASSWORD="$2"
shift 2
;;
-n|--no-cache)
USE_APT_CACHER="false"
shift
;;
-v|--verbose)
VERBOSE="true"
LOG_LEVEL="debug"
shift
;;
-h|--help)
show_usage
exit 0
;;
*)
log_error "Unknown option: $1"
show_usage
exit 1
;;
esac
done
}
# Run main function if script is executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
parse_args "$@"
main
fi