first commit

This commit is contained in:
robojerk 2025-09-05 07:10:12 -07:00
commit 7584207f76
72 changed files with 12801 additions and 0 deletions

1125
docs/calmares-installer.md Normal file

File diff suppressed because it is too large Load diff

730
docs/calmares-plan.md Normal file
View file

@ -0,0 +1,730 @@
# Calamares Module for bootc install
## Overview
This document outlines a focused plan for creating a single Calamares module that handles `bootc install` operations. This is the simplest and most direct approach, following the official bootc documentation patterns.
## Executive Summary
**Goal**: Create a single Calamares module that executes `bootc install` commands with proper configuration and error handling.
**Timeline**: 2-3 months (focused, single-purpose implementation)
**Complexity**: Low (direct tool integration)
**Target**: Debian 13 (Trixie) with bootc support
## Real-World Analysis
### How bootc install Actually Works
Based on the [official bootc documentation](https://bootc-dev.github.io/bootc//bootc-install.html) and [Fedora's bare metal documentation](https://docs.fedoraproject.org/en-US/bootc/bare-metal/):
#### 1. Core Commands
```bash
bootc install to-disk /dev/sda
bootc install to-filesystem /path/to/mounted/fs
bootc install to-existing-root
```
#### 2. Container Execution Pattern
From [Fedora's official documentation](https://docs.fedoraproject.org/en-US/bootc/bare-metal/):
```bash
podman run \
--rm --privileged \
--pid=host \
-v /dev:/dev \
-v /var/lib/containers:/var/lib/containers \
--security-opt label=type:unconfined_t \
<image> \
bootc install to-disk /path/to/disk
```
#### 3. Key Differences from Anaconda Approach
- **No kickstart files** - Direct container execution
- **No network during install** - Container is already pulled
- **Minimal configuration** - Basic installer built into bootc
- **Live ISO environment** - Typically run from Fedora CoreOS Live ISO
#### 3. Key OSTree Filesystem Nuances
**Critical differences from traditional Linux installations:**
- **Composefs by default**: [Fedora bootc uses composefs](https://docs.fedoraproject.org/en-US/bootc/filesystem/) for the root filesystem
- **Read-only root**: Filesystem is read-only at runtime (like `podman run --read-only`)
- **Special mount points**: `/etc` and `/var` are persistent, mutable bind mounts
- **Kernel location**: Kernel is in `/usr/lib/ostree-boot/` not `/boot/`
- **3-way merge**: `/etc` changes are merged across upgrades
- **Transient mountpoints**: Support for dynamic mountpoints with `transient-ro`
#### 4. Filesystem Layout
```
/usr/lib/ostree-boot/ # Kernel and initrd (not /boot/)
/etc/ # Persistent, mutable (bind mount)
/var/ # Persistent, mutable (bind mount)
/usr/ # Read-only (composefs)
/opt/ # Read-only (composefs)
```
#### 5. Authentication Patterns
From [Fedora's authentication documentation](https://docs.fedoraproject.org/en-US/bootc/authentication/):
- **Registry auth**: `/etc/ostree/auth.json` for container registries
- **SSH keys**: Via kickstart or bootc-image-builder config
- **User management**: systemd-sysusers for local users
- **nss-altfiles**: Static users in `/usr/lib/passwd` and `/usr/lib/group`
## Implementation Plan
### Phase 1: Core Module Development (Month 1)
#### 1.1 Module Structure
```cpp
class BootcInstallModule : public Calamares::Module
{
public:
void init() override;
QList<Calamares::job_ptr> jobs() const override;
private:
QString m_containerUrl;
QString m_targetDevice;
QString m_installType; // "to-disk", "to-filesystem", "to-existing-root"
bool m_authRequired;
QString m_authJson;
};
```
#### 1.2 Configuration Loading
```cpp
void BootcInstallModule::init()
{
auto config = Calamares::ModuleSystem::instance()->moduleConfiguration("bootc-install");
m_containerUrl = config.value("containerUrl").toString();
m_targetDevice = config.value("targetDevice").toString();
m_installType = config.value("installType", "to-disk").toString();
m_authRequired = config.value("authRequired", false).toBool();
m_authJson = config.value("authJson").toString();
}
```
#### 1.3 Job Implementation
```cpp
QList<Calamares::job_ptr> BootcInstallModule::jobs() const
{
QList<Calamares::job_ptr> jobs;
// Registry authentication job
if (m_authRequired) {
jobs.append(Calamares::job_ptr(new RegistryAuthJob(m_authJson)));
}
// Bootc installation job
jobs.append(Calamares::job_ptr(new BootcInstallJob(m_containerUrl, m_targetDevice, m_installType)));
// Post-install configuration job
jobs.append(Calamares::job_ptr(new BootcPostInstallJob(m_targetDevice, m_sshKey, m_username)));
return jobs;
}
```
### Phase 2: Job Implementations (Month 1-2)
#### 2.1 Registry Authentication Job
```cpp
class RegistryAuthJob : public Calamares::Job
{
public:
RegistryAuthJob(const QString& authJson) : m_authJson(authJson) {}
QString prettyName() const override { return "Configuring registry authentication"; }
Calamares::JobResult exec() override;
private:
QString m_authJson;
};
Calamares::JobResult RegistryAuthJob::exec()
{
// Create /etc/ostree directory (persistent bind mount)
if (!QDir("/etc/ostree").exists()) {
if (!QDir().mkpath("/etc/ostree")) {
return Calamares::JobResult::error("Failed to create /etc/ostree directory");
}
}
// Write auth.json (will persist across upgrades due to /etc bind mount)
QFile authFile("/etc/ostree/auth.json");
if (!authFile.open(QIODevice::WriteOnly)) {
return Calamares::JobResult::error("Failed to open /etc/ostree/auth.json for writing");
}
authFile.write(m_authJson.toUtf8());
authFile.close();
return Calamares::JobResult::ok();
}
```
#### 2.2 Bootc Install Job
```cpp
class BootcInstallJob : public Calamares::Job
{
public:
BootcInstallJob(const QString& containerUrl, const QString& targetDevice, const QString& installType)
: m_containerUrl(containerUrl), m_targetDevice(targetDevice), m_installType(installType) {}
QString prettyName() const override { return "Installing bootc container"; }
Calamares::JobResult exec() override;
private:
QString m_containerUrl;
QString m_targetDevice;
QString m_installType;
};
Calamares::JobResult BootcInstallJob::exec()
{
// Build podman command with OSTree-specific considerations
QStringList args;
args << "run" << "--rm" << "--privileged";
args << "--pid=host";
args << "-v" << "/dev:/dev";
args << "-v" << "/var/lib/containers:/var/lib/containers";
args << "--security-opt" << "label=type:unconfined_t";
// Add environment variables for OSTree filesystem
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("OSTREE_NO_SIGNATURE_VERIFICATION", "1"); // For composefs unsigned mode
env.insert("LIBMOUNT_FORCE_MOUNT2", "always"); // For transient-ro support
args << m_containerUrl;
args << "bootc" << "install" << m_installType << m_targetDevice;
// Execute podman command
QProcess process;
process.setProcessEnvironment(env);
process.start("podman", args);
if (!process.waitForFinished(-1)) {
return Calamares::JobResult::error("bootc install command timed out");
}
if (process.exitCode() != 0) {
QString error = QString("bootc install failed: %1").arg(process.readAllStandardError());
return Calamares::JobResult::error(error);
}
return Calamares::JobResult::ok();
}
```
#### 2.3 Post-Install Configuration Job
```cpp
class BootcPostInstallJob : public Calamares::Job
{
public:
BootcPostInstallJob(const QString& targetDevice, const QString& sshKey, const QString& username)
: m_targetDevice(targetDevice), m_sshKey(sshKey), m_username(username) {}
QString prettyName() const override { return "Configuring bootc system"; }
Calamares::JobResult exec() override;
private:
QString m_targetDevice;
QString m_sshKey;
QString m_username;
bool configureBootloader();
bool createUserAccount();
bool setupSshKey();
};
Calamares::JobResult BootcPostInstallJob::exec()
{
// Mount the installed system
QString mountPoint = "/mnt/bootc-install";
if (!QDir().mkpath(mountPoint)) {
return Calamares::JobResult::error("Failed to create mount point");
}
// Mount the root partition
QProcess mount;
mount.start("mount", QStringList() << m_targetDevice << mountPoint);
if (!mount.waitForFinished() || mount.exitCode() != 0) {
return Calamares::JobResult::error("Failed to mount installed system");
}
// Configure bootloader (GRUB2 for OSTree)
if (!configureBootloader()) {
return Calamares::JobResult::error("Failed to configure bootloader");
}
// Create user account
if (!createUserAccount()) {
return Calamares::JobResult::error("Failed to create user account");
}
// Setup SSH key
if (!setupSshKey()) {
return Calamares::JobResult::error("Failed to setup SSH key");
}
// Unmount
QProcess umount;
umount.start("umount", QStringList() << mountPoint);
umount.waitForFinished();
return Calamares::JobResult::ok();
}
bool BootcPostInstallJob::configureBootloader()
{
// OSTree systems use GRUB2 with specific configuration
// Kernel is in /usr/lib/ostree-boot/, not /boot/
QString grubConfig = QString("/mnt/bootc-install/boot/grub2/grub.cfg");
// Check if GRUB2 configuration exists
if (!QFile::exists(grubConfig)) {
// Run grub2-mkconfig to generate configuration
QProcess grubMkconfig;
grubMkconfig.start("grub2-mkconfig", QStringList() << "-o" << grubConfig);
if (!grubMkconfig.waitForFinished() || grubMkconfig.exitCode() != 0) {
return false;
}
}
// Install GRUB2 to the target device
QProcess grubInstall;
grubInstall.start("grub2-install", QStringList() << "--target=x86_64-efi" << m_targetDevice);
if (!grubInstall.waitForFinished() || grubInstall.exitCode() != 0) {
return false;
}
return true;
}
bool BootcPostInstallJob::createUserAccount()
{
// OSTree systems use systemd-sysusers for user management
// Users are defined in /usr/lib/sysusers.d/ or /etc/sysusers.d/
QString sysusersConfig = "/mnt/bootc-install/etc/sysusers.d/calamares-user.conf";
QString userConfig = QString("u %1 1000 \"%1\" /home/%1\n").arg(m_username);
userConfig += QString("g %1 1000\n").arg(m_username);
userConfig += QString("m %1 %1\n").arg(m_username);
QFile file(sysusersConfig);
if (!file.open(QIODevice::WriteOnly)) {
return false;
}
file.write(userConfig.toUtf8());
file.close();
return true;
}
bool BootcPostInstallJob::setupSshKey()
{
if (m_sshKey.isEmpty()) return true;
// Create .ssh directory for root
QString sshDir = "/mnt/bootc-install/root/.ssh";
if (!QDir().mkpath(sshDir)) {
return false;
}
// Write SSH key
QString keyFile = sshDir + "/authorized_keys";
QFile file(keyFile);
if (!file.open(QIODevice::WriteOnly)) {
return false;
}
file.write(m_sshKey.toUtf8());
file.close();
// Set proper permissions
QFile::setPermissions(keyFile, QFile::ReadOwner | QFile::WriteOwner);
QFile::setPermissions(sshDir, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner);
return true;
}
```
### Phase 3: OSTree Filesystem Considerations (Month 2)
#### 3.1 Filesystem Layout Validation
```cpp
class OstreeFilesystemValidator
{
public:
static bool validateTargetDevice(const QString& device);
static bool checkComposefsSupport();
static bool validateMountPoints();
private:
static bool isOstreeBootPath(const QString& path);
static bool checkTransientRoSupport();
};
bool OstreeFilesystemValidator::validateTargetDevice(const QString& device)
{
// Check if target device can support OSTree layout
// - GPT partition table required
// - EFI system partition for UEFI
// - Root partition for OSTree deployment
// - Boot partition for kernel/initrd (not /boot/ but /usr/lib/ostree-boot/)
QProcess sfdisk;
sfdisk.start("sfdisk", QStringList() << "-l" << device);
if (!sfdisk.waitForFinished()) return false;
QString output = sfdisk.readAllStandardOutput();
return output.contains("GPT") && output.contains("EFI");
}
bool OstreeFilesystemValidator::checkComposefsSupport()
{
// Check if composefs is available in the container
QProcess composefs;
composefs.start("composefs", QStringList() << "--help");
return composefs.waitForFinished() && composefs.exitCode() == 0;
}
```
#### 3.2 Kernel and Initrd Handling
```cpp
class OstreeBootManager
{
public:
static QString getKernelPath();
static QString getInitrdPath();
static bool setupBootloader(const QString& device);
static bool regenerateInitramfs(const QString& mountPoint);
private:
static const QString OSTREE_BOOT_PATH; // "/usr/lib/ostree-boot/"
};
const QString OstreeBootManager::OSTREE_BOOT_PATH = "/usr/lib/ostree-boot/";
QString OstreeBootManager::getKernelPath()
{
// Kernel is in /usr/lib/ostree-boot/, not /boot/
return OSTREE_BOOT_PATH + "vmlinuz";
}
QString OstreeBootManager::getInitrdPath()
{
// Initrd is in /usr/lib/ostree-boot/, not /boot/
return OSTREE_BOOT_PATH + "initramfs.img";
}
bool OstreeBootManager::regenerateInitramfs(const QString& mountPoint)
{
// OSTree systems need initramfs regeneration after configuration changes
// This is critical for filesystem configuration changes
QProcess dracut;
dracut.start("dracut", QStringList()
<< "--force"
<< "--hostonly"
<< "--kver" << "5.15.0" // Get actual kernel version
<< mountPoint + "/boot/initramfs.img");
if (!dracut.waitForFinished()) {
return false;
}
return dracut.exitCode() == 0;
}
```
#### 3.3 Persistent State Management
```cpp
class OstreeStateManager
{
public:
static bool setupEtcBindMount();
static bool setupVarBindMount();
static bool configureTransientRo();
private:
static bool createBindMount(const QString& source, const QString& target);
};
bool OstreeStateManager::setupEtcBindMount()
{
// /etc is a persistent, mutable bind mount
// Changes here persist across upgrades via 3-way merge
return createBindMount("/etc", "/etc");
}
bool OstreeStateManager::configureTransientRo()
{
// Enable transient-ro for dynamic mountpoints
QString configPath = "/usr/lib/ostree/prepare-root.conf";
QString config = "[root]\ntransient-ro = true\n";
QFile file(configPath);
if (!file.open(QIODevice::WriteOnly)) return false;
file.write(config.toUtf8());
file.close();
// Regenerate initramfs after config change
QProcess dracut;
dracut.start("dracut", QStringList() << "--force");
return dracut.waitForFinished() && dracut.exitCode() == 0;
}
```
### Phase 4: UI Integration (Month 2-3)
#### 4.1 Configuration Page
```cpp
class BootcInstallPage : public QWidget
{
Q_OBJECT
public:
explicit BootcInstallPage(QWidget* parent = nullptr);
QString containerUrl() const;
QString targetDevice() const;
QString installType() const;
bool authRequired() const;
QString authJson() const;
bool enableTransientRo() const;
private slots:
void onContainerUrlChanged();
void onTargetDeviceChanged();
void onInstallTypeChanged();
void onAuthRequiredChanged();
void validateOstreeRequirements();
private:
QLineEdit* m_containerUrlEdit;
QLineEdit* m_targetDeviceEdit;
QComboBox* m_installTypeCombo;
QCheckBox* m_authRequiredCheck;
QTextEdit* m_authJsonEdit;
QCheckBox* m_transientRoCheck;
QLabel* m_ostreeStatusLabel;
};
```
#### 4.2 OSTree-Aware Validation
```cpp
bool BootcInstallPage::validate()
{
if (m_containerUrlEdit->text().isEmpty()) {
Calamares::Branding::instance()->setValidationError("Container URL is required");
return false;
}
if (m_targetDeviceEdit->text().isEmpty()) {
Calamares::Branding::instance()->setValidationError("Target device is required");
return false;
}
// Validate OSTree filesystem requirements
if (!OstreeFilesystemValidator::validateTargetDevice(m_targetDeviceEdit->text())) {
Calamares::Branding::instance()->setValidationError("Target device must have GPT partition table and EFI support");
return false;
}
if (!OstreeFilesystemValidator::checkComposefsSupport()) {
Calamares::Branding::instance()->setValidationError("Composefs support not available in container");
return false;
}
if (m_authRequiredCheck->isChecked() && m_authJsonEdit->toPlainText().isEmpty()) {
Calamares::Branding::instance()->setValidationError("Authentication JSON is required");
return false;
}
return true;
}
void BootcInstallPage::validateOstreeRequirements()
{
// Real-time validation of OSTree requirements
bool deviceValid = OstreeFilesystemValidator::validateTargetDevice(m_targetDeviceEdit->text());
bool composefsValid = OstreeFilesystemValidator::checkComposefsSupport();
QString status;
if (deviceValid && composefsValid) {
status = "✓ OSTree requirements satisfied";
m_ostreeStatusLabel->setStyleSheet("color: green;");
} else {
status = "✗ OSTree requirements not met";
m_ostreeStatusLabel->setStyleSheet("color: red;");
}
m_ostreeStatusLabel->setText(status);
}
```
### Phase 4: Testing and Polish (Month 2-3)
#### 4.1 Unit Tests
```cpp
class BootcInstallModuleTest : public QObject
{
Q_OBJECT
private slots:
void testModuleInitialization();
void testJobCreation();
void testRegistryAuthJob();
void testBootcInstallJob();
void testValidation();
};
```
#### 4.2 Integration Tests
- [ ] Test with real bootc containers
- [ ] Test registry authentication
- [ ] Test different install types
- [ ] Test error handling
## Configuration
### Module Configuration
```yaml
# bootc-install.conf
module: bootc-install
config:
containerUrl: "quay.io/centos-bootc/centos-bootc:stream9"
targetDevice: "/dev/sda"
installType: "to-disk" # to-disk, to-filesystem, to-existing-root
authRequired: false
authJson: ""
# User account configuration
username: "admin"
sshKey: "" # SSH public key for root access
# OSTree-specific configuration
ostree:
enableComposefs: true
enableTransientRo: false
kernelPath: "/usr/lib/ostree-boot/vmlinuz"
initrdPath: "/usr/lib/ostree-boot/initramfs.img"
bootPath: "/usr/lib/ostree-boot/"
# Bootloader configuration
bootloader:
type: "grub2"
target: "x86_64-efi"
regenerateInitramfs: true
# Filesystem validation
validation:
requireGpt: true
requireEfi: true
checkComposefs: true
validateMountPoints: true
```
### Calamares Integration
```yaml
# calamares.conf
modules:
- bootc-install
bootc-install:
containerUrl: "quay.io/centos-bootc/centos-bootc:stream9"
targetDevice: "/dev/sda"
installType: "to-disk"
authRequired: false
# OSTree filesystem settings
ostree:
enableComposefs: true
enableTransientRo: false
```
## Technical Architecture
### File Structure
```
calamares-bootc-install/
├── src/
│ ├── BootcInstallModule.cpp
│ ├── BootcInstallJob.cpp
│ ├── RegistryAuthJob.cpp
│ ├── BootcInstallPage.cpp
│ └── BootcInstallPage.ui
├── config/
│ └── bootc-install.conf
├── tests/
│ ├── BootcInstallModuleTest.cpp
│ └── testdata/
└── CMakeLists.txt
```
### Dependencies
- **Calamares**: Module framework
- **Qt**: UI and core functionality
- **podman**: Container runtime
- **bootc**: Container installation tool
## Key Implementation Details
### 1. Simple and Focused
- **Single purpose**: Only handles `bootc install`
- **Direct integration**: Calls podman and bootc directly
- **Minimal complexity**: No pattern switching or hybrid approaches
### 2. Follow Official Patterns
- **Use exact podman command** from Fedora documentation
- **Follow bootc install syntax** from official docs
- **Handle registry auth** via `/etc/ostree/auth.json`
### 3. Error Handling
- **Validate inputs** before execution
- **Handle podman failures** gracefully
- **Provide clear error messages** to users
## Success Metrics
### Technical Metrics
- [ ] Module loads and initializes correctly
- [ ] Jobs execute successfully
- [ ] Registry authentication works
- [ ] bootc install completes successfully
### User Experience Metrics
- [ ] Clear configuration UI
- [ ] Proper validation and error messages
- [ ] Progress reporting during installation
- [ ] Integration with Calamares workflow
## Conclusion
This focused plan creates a single, purpose-built Calamares module for `bootc install` operations that properly accounts for the unique OSTree filesystem characteristics and the specific nuances of direct container installation. By following the [official bootc bare metal documentation](https://docs.fedoraproject.org/en-US/bootc/bare-metal/) exactly and incorporating the specific requirements for bootloader configuration, initramfs handling, and user account creation, we can create a reliable, maintainable solution.
### Key bootc install Considerations Addressed:
1. **Direct Container Execution** - Uses [podman run with privileged mode](https://docs.fedoraproject.org/en-US/bootc/bare-metal/) for installation
2. **Post-Install Configuration** - Handles bootloader setup, user creation, and SSH key configuration
3. **OSTree Filesystem Layout** - Kernel in `/usr/lib/ostree-boot/` not `/boot/`
4. **GRUB2 Configuration** - Proper bootloader setup for OSTree systems
5. **Initramfs Regeneration** - Critical for filesystem configuration changes
6. **User Account Management** - Uses systemd-sysusers for OSTree-compatible user creation
7. **SSH Key Setup** - Proper permissions and directory structure for root access
### Key Advantages:
1. **bootc install Native** - Follows the [official bootc install approach](https://docs.fedoraproject.org/en-US/bootc/bare-metal/) exactly
2. **Complete Installation** - Handles both installation and post-install configuration
3. **OSTree-Aware** - Properly manages filesystem layout and bootloader configuration
4. **User-Friendly** - Provides familiar Calamares interface for bootc installation
5. **Validation** - Real-time checking of OSTree and bootc requirements
6. **Extensibility** - Can be enhanced with additional features over time
This approach ensures that the Calamares module provides a complete, user-friendly interface for `bootc install` operations while properly handling all the OSTree-specific requirements for bootloader configuration, initramfs management, and user account creation.

300
docs/debian-installer.md Normal file
View file

@ -0,0 +1,300 @@
# Debian Installer Integration
## Overview
This document explores how to integrate debian-installer (d-i) support into the debian-bootc-image-builder project, examining the traditional debian-installer build process and potential integration approaches.
## Traditional Debian Installer Build Process
### Core Toolchain
The official debian-installer is built using a structured toolchain:
- **Primary Tool**: `Makefile` in `debian-installer/build/` directory
- **Build System**: Make-based with structured targets and dependencies
- **Dependencies**: Listed in `installer/debian/control` file
- **Environment**: Requires Debian unstable (sid) or sid chroot
### Directory Structure
```
debian-installer/
├── build/
│ ├── Makefile # Main build orchestrator
│ ├── util/ # Helper scripts
│ ├── config/ # Build targets per architecture
│ ├── pkg-lists/ # udeb packages for each image type
│ ├── boot/ # Boot configuration files
│ └── localudebs/ # Custom udebs not in standard mirror
```
### Key Components
- **udebs**: Debian Installer packages (specialized for installer environment)
- **pkg-lists**: Define which udebs are included in each image type
- **config**: Architecture-specific build targets and supported media types
- **boot**: Bootloader configuration for different boot methods
### Build Process
1. **Setup**: Ensure build dependencies are satisfied
2. **Targets**: Use make commands like `build_cdrom_isolinux`, `build_netboot`
3. **Cleanup**: Run `make reallyclean` between builds
## Alternative Tools
### simple-cdd
- **Purpose**: Create custom Debian installation CDs
- **Approach**: Configuration-driven, uses debian-installer as base
- **Use Case**: Custom distributions, pre-configured installs
- **Advantage**: Simpler than full d-i build system
### debian-cd
- **Purpose**: Official Debian CD/DVD creation
- **Approach**: Complex build system for official releases
- **Use Case**: Official Debian releases
- **Complexity**: High, designed for official distribution
## Integration Approaches
### Option 1: Hybrid Approach (Recommended)
- **Disk Images**: Use OSBuild (qcow2, ami, vmdk, raw)
- **debian-installer**: Use simple-cdd integration
- **Shared Configuration**: Leverage existing `.config/registry.yaml` system
**Advantages:**
- Uses each tool for its intended purpose
- OSBuild excels at disk images
- simple-cdd is proven for installer creation
- Maintains project focus and simplicity
### Option 2: OSBuild Extension
- **Approach**: Extend OSBuild with debian-installer stages
- **Complexity**: High - requires OSBuild modifications
- **Maintenance**: Ongoing OSBuild integration work
### Option 3: Focus on Disk Images Only
- **Approach**: Remove installer support entirely
- **Focus**: Pure disk image creation with OSBuild
- **Simplicity**: Maximum focus and maintainability
## Implementation Strategy
### Recommended: simple-cdd Integration
1. **Add debian-installer command**:
```bash
debian-bootc-image-builder installer --type debian-installer
```
2. **Configuration Integration**:
- Extend `.config/registry.yaml` with installer settings
- Support debian-installer specific configurations
- Maintain consistency with existing config system
3. **Build Process**:
- Use simple-cdd for installer creation
- Integrate with existing container workflow
- Leverage existing APT integration
4. **Package Management**:
- Use existing APT solver for udeb resolution
- Extend package definitions for installer packages
- Maintain consistency with disk image approach
## Comparison: Fedora vs Debian Approach
### Fedora (anaconda)
- **OSBuild Integration**: Native support via `org.osbuild.anaconda` stage
- **Package-Based**: Uses RPM packages in YAML definitions
- **Pipeline**: Multi-stage OSBuild pipeline (build → anaconda-tree → bootiso)
- **Configuration**: Blueprint format with anaconda module support
### Debian (debian-installer)
- **Traditional Toolchain**: Make-based build system
- **Package-Based**: Uses udeb packages (installer-specific)
- **Alternative Tools**: simple-cdd, debian-cd
- **Configuration**: Various formats (simple-cdd config, debian-cd config)
## Recommendation
**Use the Hybrid Approach** with simple-cdd integration:
1. **Keep OSBuild for disk images** - it's designed for this purpose
2. **Use simple-cdd for debian-installer** - proven, maintained tool
3. **Share configuration system** - extend `.config/registry.yaml`
4. **Maintain consistency** - use existing APT integration
This approach provides:
- ✅ **Best tool for each job**
- ✅ **Proven, maintained tools**
- ✅ **Consistent user experience**
- ✅ **Manageable complexity**
- ✅ **Clear separation of concerns**
## Technical Hurdles and Challenges
### Understanding the Installation Flow
#### How Anaconda Integrates with Bootc
The Fedora anaconda approach provides a clear model for understanding the technical challenges:
1. **Anaconda ISO Creation**: OSBuild generates an anaconda ISO with embedded kickstart configuration
2. **Kickstart Integration**: The `ostreecontainer --url <container-image>` directive tells anaconda to install the bootc container
3. **Installation Process**: Anaconda downloads the container and calls `bootc install` internally
4. **System Configuration**: The installed system boots into the OSTree-based bootc environment
#### Key Technical Challenge: Preseed vs Kickstart
- **Fedora**: Uses kickstart with `ostreecontainer` directive
- **Debian**: Uses preseed configuration system
- **Challenge**: No equivalent `ostreecontainer` directive exists in debian-installer preseed
### Major Technical Hurdles
#### 1. Preseed Integration Challenge
**Problem**: Debian-installer uses preseed, not kickstart
- **Preseed limitations**: No built-in support for container installation
- **Custom integration needed**: Must create custom preseed hooks or scripts
- **Complexity**: Requires deep understanding of debian-installer internals
**Potential Solutions**:
- **Custom preseed script**: Create preseed hook that downloads and installs bootc container
- **Modified debian-installer**: Extend debian-installer with bootc support
- **Post-installation script**: Install bootc after base system installation
#### 2. Bootc Installation Integration
**Problem**: How to integrate `bootc install` into debian-installer workflow
- **Timing**: When during installation should bootc install run?
- **Dependencies**: bootc must be available in the installer environment
- **Partitioning**: Must align with debian-installer's partitioning scheme
**Technical Requirements**:
- **bootc package**: Must be available in installer environment (udeb)
- **Container download**: Network access during installation
- **Installation order**: Partition → Format → bootc install → Configure bootloader
#### 3. Package Management Complexity
**Problem**: Different package systems between installer and target
- **Installer packages**: udebs (debian-installer packages)
- **Target packages**: Regular .deb packages
- **bootc package**: Must be available as both udeb and .deb
**Challenges**:
- **Package availability**: bootc may not be available as udeb
- **Dependency resolution**: Different dependency trees for installer vs target
- **Repository management**: Different repositories for installer vs target
#### 4. Bootloader Configuration
**Problem**: Bootloader setup for bootc systems
- **GRUB configuration**: Must support OSTree-based booting
- **Kernel parameters**: Special parameters for bootc/OSTree systems
- **UEFI/BIOS support**: Different bootloader requirements
**Technical Details**:
- **OSTree integration**: GRUB must understand OSTree deployments
- **Kernel selection**: Must boot correct kernel from OSTree deployment
- **Initramfs**: May need custom initramfs for bootc systems
#### 5. Network and Container Access
**Problem**: Container registry access during installation
- **Network configuration**: Must have network access during installation
- **Registry authentication**: May need credentials for private registries
- **Container download**: Large container images during installation
**Challenges**:
- **Offline installation**: How to handle offline scenarios?
- **Bandwidth**: Large container downloads during installation
- **Authentication**: Registry credentials management
### Implementation Complexity Analysis
#### Simple-cdd Integration Challenges
**Advantages**:
- ✅ **Proven tool**: Well-maintained and documented
- ✅ **Configuration-driven**: Fits existing config system
- ✅ **Debian-native**: Designed for Debian systems
**Challenges**:
- ❌ **Learning curve**: Complex configuration system
- ❌ **bootc integration**: No built-in bootc support
- ❌ **Customization needed**: Significant modification required
#### OSBuild Extension Challenges
**Advantages**:
- ✅ **Consistent approach**: Same tool for disk images and installers
- ✅ **Existing integration**: Already integrated with project
**Challenges**:
- ❌ **No debian-installer support**: OSBuild doesn't support debian-installer
- ❌ **Major development**: Would require significant OSBuild modifications
- ❌ **Maintenance burden**: Ongoing OSBuild integration work
#### Direct debian-installer Modification
**Advantages**:
- ✅ **Native integration**: Built into debian-installer
- ✅ **Clean approach**: No external tool dependencies
**Challenges**:
- ❌ **Complex development**: Requires deep debian-installer knowledge
- ❌ **Upstream integration**: Changes need to be accepted upstream
- ❌ **Maintenance**: Ongoing debian-installer integration
### Risk Assessment
#### High Risk Factors
1. **Preseed limitations**: No proven way to integrate bootc installation
2. **Package availability**: bootc may not be available as udeb
3. **Bootloader complexity**: OSTree bootloader configuration is complex
4. **Network dependencies**: Container download during installation
#### Medium Risk Factors
1. **simple-cdd learning curve**: Complex configuration system
2. **Testing complexity**: Difficult to test installer integration
3. **Documentation gaps**: Limited documentation for custom installer creation
#### Low Risk Factors
1. **Existing APT integration**: Can leverage existing package resolution
2. **Configuration system**: Existing config system can be extended
3. **Container workflow**: Existing container handling can be reused
### Recommended Approach: Phased Implementation
#### Phase 1: Research and Prototype
1. **Investigate preseed hooks**: Research custom preseed script capabilities
2. **Test bootc availability**: Check if bootc is available as udeb
3. **Prototype simple-cdd**: Create basic simple-cdd configuration
4. **Test container download**: Verify network access during installation
#### Phase 2: Basic Integration
1. **Create preseed script**: Develop custom preseed hook for bootc installation
2. **Integrate with simple-cdd**: Add bootc support to simple-cdd configuration
3. **Test basic workflow**: Verify end-to-end installation process
#### Phase 3: Production Ready
1. **Error handling**: Add comprehensive error handling and recovery
2. **Documentation**: Create user documentation and examples
3. **Testing**: Comprehensive testing across different scenarios
### Alternative: Focus on Disk Images Only
Given the technical complexity, consider **removing installer support entirely**:
**Advantages**:
- ✅ **Simplified project**: Focus on core disk image functionality
- ✅ **Reduced complexity**: No installer integration challenges
- ✅ **Faster development**: Can focus on disk image improvements
- ✅ **Clear scope**: Well-defined project boundaries
**Disadvantages**:
- ❌ **Limited use cases**: No installer-based deployment
- ❌ **User expectations**: Users may expect installer support
- ❌ **Feature parity**: Less feature-complete than Fedora version
## Next Steps
1. **Research preseed hooks** and custom script capabilities
2. **Investigate bootc udeb availability** in Debian repositories
3. **Prototype simple-cdd integration** with basic bootc support
4. **Test container download** during installation process
5. **Evaluate complexity** vs. benefit of installer support
6. **Consider focusing on disk images only** if complexity is too high

348
docs/fedora-ignition.md Normal file
View file

@ -0,0 +1,348 @@
# Fedora Ignition Approach for Bootc Installation
## Overview
Fedora CoreOS uses **Ignition** instead of traditional kickstart for system configuration and bootc installation. Ignition is a modern, JSON-based configuration system designed for immutable infrastructure and container-first deployments.
## Key Technical Concepts
### 1. Ignition vs Kickstart
| Aspect | Ignition | Kickstart |
|--------|----------|-----------|
| **Format** | JSON | Shell-like syntax |
| **Purpose** | Immutable infrastructure | Package-based installation |
| **Configuration** | Declarative | Imperative |
| **Container Support** | Native | Via `ostreecontainer` directive |
| **Modernity** | Modern, cloud-native | Traditional, legacy |
### 2. Ignition Configuration Structure
```json
{
"ignition": {
"version": "3.4.0"
},
"storage": {
"disks": [
{
"device": "/dev/sda",
"partitions": [
{
"label": "BIOS-BOOT",
"number": 1,
"size": 1024
},
{
"label": "EFI-SYSTEM",
"number": 2,
"size": 268435456
},
{
"label": "ROOT",
"number": 3,
"size": 0
}
]
}
],
"filesystems": [
{
"device": "/dev/disk/by-partlabel/ROOT",
"format": "xfs",
"path": "/"
}
]
},
"systemd": {
"units": [
{
"name": "bootc-install.service",
"enabled": true,
"contents": "[Unit]\nDescription=Install bootc container\n[Service]\nType=oneshot\nExecStart=/usr/bin/bootc install to-disk /dev/sda\n[Install]\nWantedBy=multi-user.target"
}
]
}
}
```
### 3. Container Installation via Ignition
#### Method 1: Systemd Service
```json
{
"systemd": {
"units": [
{
"name": "bootc-install.service",
"enabled": true,
"contents": "[Unit]\nDescription=Install bootc container\n[Service]\nType=oneshot\nExecStart=/usr/bin/bootc install to-disk /dev/sda\n[Install]\nWantedBy=multi-user.target"
}
]
}
}
```
#### Method 2: Direct Container Pull
```json
{
"storage": {
"files": [
{
"path": "/etc/containers/registries.conf.d/bootc.conf",
"mode": 420,
"contents": {
"source": "data:text/plain;base64,W1JlZ2lzdHJ5XQpsb2NhdGlvbj0icXVheS5pbyIKc2VjdXJlPWZhbHNlCg=="
}
}
]
}
}
```
## Fedora CoreOS ISO Analysis
### ISO Structure
```
fedora-coreos-42.20250803.3.0-live-iso.x86_64.iso
├── coreos/
│ ├── features.json # Installer capabilities
│ ├── igninfo.json # Points to ignition.img
│ ├── kargs.json # Kernel arguments
│ └── miniso.dat # Minimal ISO data
├── images/
│ ├── ignition.img # Ignition configuration
│ ├── initrd.img # Initial ramdisk
│ ├── rootfs.img # Root filesystem
│ └── vmlinuz # Kernel
├── EFI/fedora/grub.cfg # EFI boot configuration
└── isolinux/isolinux.cfg # BIOS boot configuration
```
### Boot Configuration
- **Kernel arguments**: `coreos.liveiso=fedora-coreos-42.20250803.3.0 ignition.firstboot ignition.platform.id=metal`
- **Ignition integration**: `ignition.img` loaded as initrd
- **No kickstart references** in boot configuration
### Features Capabilities
```json
{
"installer-config": true,
"installer-config-directives": {
"append-karg": true,
"architecture": true,
"console": true,
"copy-network": true,
"delete-karg": true,
"dest-device": true,
"fetch-retries": true,
"ignition-file": true,
"ignition-hash": true,
"ignition-url": true,
"image-file": true,
"image-url": true,
"insecure": true,
"insecure-ignition": true,
"network-dir": true,
"offline": true,
"platform": true,
"preserve-on-error": true,
"save-partindex": true,
"save-partlabel": true,
"secure-ipl": true,
"stream": true,
"stream-base-url": true
},
"live-initrd-network": true
}
```
## Ignition Configuration Examples
### 1. Basic Bootc Installation
```json
{
"ignition": {
"version": "3.4.0"
},
"storage": {
"disks": [
{
"device": "/dev/sda",
"wipeTable": true,
"partitions": [
{
"label": "BIOS-BOOT",
"number": 1,
"size": 1024,
"typeGuid": "21686148-6449-6E6F-744E-656564454649"
},
{
"label": "EFI-SYSTEM",
"number": 2,
"size": 268435456,
"typeGuid": "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
},
{
"label": "ROOT",
"number": 3,
"size": 0,
"typeGuid": "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709"
}
]
}
],
"filesystems": [
{
"device": "/dev/disk/by-partlabel/ROOT",
"format": "xfs",
"path": "/"
}
]
},
"systemd": {
"units": [
{
"name": "bootc-install.service",
"enabled": true,
"contents": "[Unit]\nDescription=Install bootc container\n[Service]\nType=oneshot\nExecStart=/usr/bin/bootc install to-disk /dev/sda\n[Install]\nWantedBy=multi-user.target"
}
]
}
}
```
### 2. Registry Authentication
```json
{
"ignition": {
"version": "3.4.0"
},
"storage": {
"files": [
{
"path": "/etc/ostree/auth.json",
"mode": 420,
"contents": {
"source": "data:text/plain;base64,ewogICJhdXRocyI6IHsKICAgICJxdWF5LmlvIjogewogICAgICAiYXV0aCI6ICI8eW91ciBzZWNyZXQgaGVyZT4iCiAgICB9CiAgfQp9"
}
},
{
"path": "/etc/containers/registries.conf.d/bootc.conf",
"mode": 420,
"contents": {
"source": "data:text/plain;base64,W1JlZ2lzdHJ5XQpsb2NhdGlvbj0icXVheS5pbyIKc2VjdXJlPWZhbHNlCg=="
}
}
]
}
}
```
### 3. Network Configuration
```json
{
"ignition": {
"version": "3.4.0"
},
"networkd": {
"units": [
{
"name": "00-eth0.network",
"contents": "[Match]\nName=eth0\n[Network]\nDHCP=yes"
}
]
}
}
```
## Advantages of Ignition Approach
### 1. Modern Design
- **JSON-based** - easy to generate programmatically
- **Declarative** - describes desired state, not steps
- **Immutable** - configuration is applied once
- **Cloud-native** - designed for modern infrastructure
### 2. Container Integration
- **Native container support** - no special directives needed
- **Registry authentication** - built-in support
- **Container runtime** - integrated by default
- **Bootc compatibility** - works seamlessly with bootc
### 3. Flexibility
- **Modular** - can combine different configuration sources
- **Extensible** - easy to add new configuration types
- **Versioned** - configuration format is versioned
- **Validated** - JSON schema validation
## Implementation for Debian
### Calamares Integration
1. **Generate Ignition JSON** from Calamares configuration
2. **Create custom module** for container installation
3. **Handle registry authentication** via Ignition
4. **Integrate with bootc** installation process
### debian-installer Integration
1. **Replace preseed** with Ignition configuration
2. **Add container runtime** to installer environment
3. **Implement Ignition parser** in installer
4. **Handle container installation** via systemd units
### Key Implementation Steps
1. **Study Ignition specification** and examples
2. **Design JSON generation** from user input
3. **Implement container installation** logic
4. **Handle registry authentication** and configuration
5. **Test with real bootc containers**
## Comparison: Ignition vs Kickstart vs Preseed
| Feature | Ignition | Kickstart | Preseed |
|---------|----------|-----------|---------|
| **Format** | JSON | Shell-like | Debian-specific |
| **Container Support** | Native | Via directive | None |
| **Modernity** | High | Medium | Low |
| **Flexibility** | High | Medium | Low |
| **Validation** | Schema-based | Runtime | Limited |
| **Cloud Integration** | Excellent | Good | Poor |
| **Immutable Design** | Yes | No | No |
## Tools and Resources
### CoreOS Installer
- **`coreos-installer`** - tool for creating custom ISOs
- **`butane`** - YAML to Ignition converter
- **`ignition-validate`** - configuration validator
### Configuration Examples
- **Fedora CoreOS examples** - official configuration samples
- **Butane configs** - YAML-based Ignition generation
- **Container installation** - bootc integration patterns
### Documentation
- [Ignition specification](https://coreos.github.io/ignition/)
- [Butane documentation](https://coreos.github.io/butane/)
- [CoreOS installer](https://coreos.github.io/coreos-installer/)
## Next Steps for Implementation
1. **Study Ignition examples** for container installation
2. **Design JSON generation** from user configuration
3. **Implement Calamares module** for Ignition support
4. **Create debian-installer** Ignition integration
5. **Test with real bootc containers** and registries
## Conclusion
The Ignition approach used by Fedora CoreOS is **more modern and suitable** for our Debian bootc-image-builder than traditional kickstart or preseed. Its JSON-based configuration, native container support, and immutable design make it ideal for container-first deployments.
Key advantages:
- **Easier to generate** programmatically
- **More flexible** than kickstart/preseed
- **Container-native** by design
- **Better suited** for modern infrastructure
- **Future-proof** approach
This makes Ignition the recommended approach for both Calamares and debian-installer integration in our Debian bootc-image-builder project.

283
docs/fedora-kickstart.md Normal file
View file

@ -0,0 +1,283 @@
# Fedora Kickstart Approach for Bootc Installation
## Overview
Fedora uses a sophisticated kickstart-based approach for bootc installation that is fundamentally different from traditional package-based installations. The key insight is that **bootc installations are container-first, not package-first**.
## Key Technical Concepts
### 1. The `ostreecontainer` Directive
The `ostreecontainer` kickstart directive is the core mechanism for bootc installation:
```kickstart
ostreecontainer --url quay.io/centos-bootc/centos-bootc:stream9
```
**Key characteristics:**
- **No `%packages` section** - the entire system is container-based
- **Registry URL** specifies the container image to install
- **Authentication** handled separately via registry configuration
- **Partitioning** still required, but no package management
### 1.1. Complete `ostreecontainer` Parameters
Based on analysis of the Fedora COSMIC Atomic ISO, the full parameter set is:
```kickstart
ostreecontainer --url="quay.io/exampleos/foo:latest" \
--stateroot="default" \
--remote="default" \
--transport="registry" \
--no-signature-verification
```
**Parameter details:**
- **`--url`** (required): Container image URL (e.g., `quay.io/exampleos/foo:latest`)
- **`--stateroot`**: Name for the state directory (default: `default`)
- **`--remote`**: Name of the OSTree remote (default: same as stateroot)
- **`--transport`**: Transport method (default: `registry`)
- **`--no-signature-verification`**: Disable signature verification (optional)
### 1.2. Implementation Details
**Python-based implementation** in PyKickstart:
- **File**: `/usr/lib/python3.13/site-packages/pykickstart/commands/ostreecontainer.py`
- **Class**: `F38_OSTreeContainer` (available in Fedora 38+)
- **Conflicts**: Cannot be used with `ostreesetup` directive
- **Experimental**: Marked as experimental in documentation
### 2. Kickstart Infrastructure
Based on analysis of the Fedora COSMIC Atomic ISO, the kickstart system includes:
#### 2.1. Dracut Hooks
- **`50-kickstart-genrules.sh`**: Generates udev rules for fetching kickstarts
- **`11-fetch-kickstart-net.sh`**: Fetches kickstart files from network
- **`26-parse-anaconda-kickstart.sh`**: Handles kickstart command line parsing
#### 2.2. Anaconda Integration
- **PyKickstart library**: Python-based kickstart parsing
- **Command handlers**: Including `ostreecontainer` and `ostreesetup`
- **Version support**: Fedora 38+ includes `ostreecontainer` support
#### 2.3. Kickstart Fetching Methods
- **Network**: HTTP, HTTPS, FTP, NFS
- **Local**: CDROM, hard disk
- **Multiple URLs**: Support for fallback kickstart locations
### 3. Registry Authentication
Fedora handles registry access through kickstart `%pre` sections:
#### Basic Authentication
```kickstart
%pre
mkdir -p /etc/ostree
cat > /etc/ostree/auth.json << 'EOF'
{
"auths": {
"quay.io": {
"auth": "<your secret here>"
}
}
}
EOF
%end
```
#### Insecure Registry Support
```kickstart
%pre
mkdir -p /etc/containers/registries.conf.d/
cat > /etc/containers/registries.conf.d/local-registry.conf << 'EOF'
[[registry]]
location="[IP_Address]:5000"
insecure=true
EOF
%end
```
### 4. Complete Kickstart Example
```kickstart
# Basic setup
text
network --bootproto=dhcp --device=link --activate
# Basic partitioning
clearpart --all --initlabel --disklabel=gpt
reqpart --add-boot
part / --grow --fstype xfs
# Container installation - NO %packages section!
ostreecontainer --url quay.io/centos-bootc/centos-bootc:stream9
# System configuration
firewall --disabled
services --enabled=sshd
rootpw --iscrypted locked
sshkey --username root "<your key here>"
reboot
```
## Installation Methods Analysis
### Fedora COSMIC Atomic vs Fedora CoreOS
**Key Discovery**: Different Fedora variants use different approaches:
| Variant | Configuration System | Container Support | Use Case |
|---------|---------------------|-------------------|----------|
| **Fedora COSMIC Atomic** | Kickstart + `ostreecontainer` | Native | Traditional server/workstation |
| **Fedora CoreOS** | Ignition | Native | Container-first, immutable |
| **Fedora Server/Workstation** | Kickstart + `ostreecontainer` | Native | Traditional Linux |
## Three Installation Methods
### 1. Stock Anaconda ISO/PXE (Network-based)
- Uses standard Fedora installer with custom kickstart
- Requires network access during installation
- Container image fetched from registry
- **Advantage**: Uses existing installer infrastructure
- **Disadvantage**: Requires network connectivity
### 2. Custom Installer ISO (bootc-image-builder generated)
- Uses `anaconda-iso` type in bootc-image-builder
- Container image **embedded in the ISO**
- No network access needed during installation
- **Advantage**: Air-gapped installation possible
- **Disadvantage**: Larger ISO size
### 3. Direct Container Installation (`bootc install`)
- Uses `bootc install to-disk` or `bootc install to-filesystem`
- Container image is the "source of truth"
- Can be run from any Linux environment
- **Advantage**: Most flexible, container-native
- **Disadvantage**: Requires existing Linux environment
## Technical Implementation Details
### Container Runtime Requirements
- **Podman** or **containerd** must be available in installer environment
- **Registry access** configured via `/etc/containers/registries.conf.d/`
- **Authentication** handled via `/etc/ostree/auth.json`
### Partitioning Strategy
- **GPT partition table** required
- **Boot partition** for EFI/BIOS boot
- **Root partition** for container installation
- **No package management** - all content from container
### Network Configuration
- **DHCP** for basic network access
- **Registry connectivity** for container pull
- **Optional**: Static IP configuration
## Implications for Debian Implementation
### Calamares Integration
1. **Custom module needed** to handle `ostreecontainer` equivalent
2. **Registry authentication** must be implemented
3. **Container runtime** must be available
4. **Partitioning** handled before container installation
### debian-installer Integration
1. **Preseed extension** needed for container support
2. **Container runtime** added to installer environment
3. **Registry configuration** in installer
4. **Major architectural change** from package-based to container-based
### Key Differences from Traditional Installation
- **No package management** during installation
- **Container-first** approach
- **Registry authentication** required
- **Partitioning** still needed but simpler
- **System configuration** via kickstart/preseed
## Registry Handling Patterns
### Authentication Methods
1. **Username/password** via auth.json
2. **Token-based** authentication
3. **Certificate-based** authentication
4. **Insecure registry** support for development
### Configuration Locations
- **`/etc/ostree/auth.json`** - authentication credentials
- **`/etc/containers/registries.conf.d/`** - registry configuration
- **`/etc/pki/ca-trust/source/anchors/`** - certificate authorities
## Security Considerations
### Registry Security
- **TLS verification** by default
- **Insecure registries** only for development
- **Certificate management** for custom CAs
- **Authentication** required for private registries
### Container Security
- **Image verification** via signatures
- **Content trust** mechanisms
- **Runtime security** via container runtime
## Advantages of This Approach
1. **Container-native** - aligns with modern deployment patterns
2. **Atomic updates** - via ostree/bootc upgrade
3. **Immutable systems** - reduces configuration drift
4. **Registry integration** - leverages existing container infrastructure
5. **Air-gapped support** - via embedded ISO approach
## Challenges for Debian
1. **Preseed lacks `ostreecontainer` equivalent** - major technical hurdle
2. **Container runtime** not standard in debian-installer
3. **Registry authentication** not built into installer
4. **Architectural shift** from package-based to container-based
5. **Tooling gaps** - need custom modules/extensions
## Real-World Implementation Analysis
### Fedora COSMIC Atomic ISO Structure
```
Fedora-COSMIC-Atomic-ostree-x86_64-42-1.1.iso
├── boot/grub2/grub.cfg # BIOS boot configuration
├── EFI/BOOT/grub.cfg # EFI boot configuration
├── images/
│ ├── install.img # Anaconda installer image
│ ├── pxeboot/
│ │ ├── initrd.img # XZ-compressed initrd
│ │ └── vmlinuz # Kernel
│ └── eltorito.img # El Torito boot image
└── Fedora-Legal-README.txt # Legal information
```
### Kickstart Processing Pipeline
1. **Boot**: Kernel loads with kickstart parameters
2. **Dracut**: Hooks process kickstart fetching
3. **Anaconda**: PyKickstart parses configuration
4. **Installation**: `ostreecontainer` directive triggers container installation
5. **Configuration**: System setup via kickstart commands
### Key Implementation Files
- **`ostreecontainer.py`**: Core directive implementation
- **`f42.py`**: Fedora 42 handler with `ostreecontainer` support
- **Dracut hooks**: Network and disk kickstart fetching
- **Anaconda modules**: Integration with installer
## Next Steps for Implementation
1. **Study `ostreecontainer` implementation** in Anaconda
2. **Design Calamares module** for container installation
3. **Extend preseed** for container support
4. **Implement registry handling** in both approaches
5. **Test container installation** workflows
6. **Choose approach**: Kickstart (traditional) vs Ignition (modern)
## References
- [Fedora bootc bare metal installation guide](https://docs.fedoraproject.org/en-US/bootc/bare-metal/)
- [Kickstart ostreecontainer documentation](https://pykickstart.readthedocs.io/en/latest/kickstart-docs.html#ostreecontainer)
- [bootc-image-builder documentation](https://github.com/osbuild/bootc-image-builder)
- [bib-kickstart-demo repository](https://github.com/osbuild/bib-kickstart-demo)

View file

@ -0,0 +1,369 @@
# Ignition vs Calamares: Comparison for Debian Bootc-Image-Builder
## Overview
This document compares Ignition and Calamares as potential approaches for implementing installer support in our Debian bootc-image-builder project. Both offer different advantages and trade-offs for container-first installation.
## Executive Summary
| Aspect | Winner | Reasoning |
|--------|--------|-----------|
| **Container Integration** | Ignition | Native container support, designed for immutable infrastructure |
| **Modern Architecture** | Ignition | JSON-based, declarative, cloud-native |
| **User Experience** | Calamares | Graphical interface, familiar to users |
| **Debian Integration** | Calamares | Already used in Debian, better ecosystem fit |
| **Development Complexity** | Calamares | Existing framework, less custom development |
| **Flexibility** | Ignition | More modular, easier to extend |
## Detailed Comparison
### 1. Architecture and Design Philosophy
#### Ignition
- **Declarative**: Describes desired system state
- **Immutable**: Configuration applied once, system remains unchanged
- **Container-first**: Designed for modern container workloads
- **JSON-based**: Easy to generate programmatically
- **Cloud-native**: Optimized for infrastructure automation
#### Calamares
- **Interactive**: User-driven configuration process
- **Mutable**: Allows system modifications after installation
- **Distribution-agnostic**: Works across different Linux distributions
- **C++/Python**: Mixed language implementation
- **Desktop-focused**: Originally designed for desktop installations
### 2. Container Integration
Based on analysis of Fedora's approaches, both Ignition and Calamares can effectively handle bootc installation:
#### Ignition (Fedora CoreOS Pattern)
```json
{
"systemd": {
"units": [
{
"name": "bootc-install.service",
"enabled": true,
"contents": "[Unit]\nDescription=Install bootc container\n[Service]\nType=oneshot\nExecStart=/usr/bin/bootc install to-disk /dev/sda\n[Install]\nWantedBy=multi-user.target"
}
]
},
"storage": {
"files": [
{
"path": "/etc/ostree/auth.json",
"mode": 420,
"contents": {
"source": "data:text/plain;base64,ewogICJhdXRocyI6IHsKICAgICJxdWF5LmlvIjogewogICAgICAiYXV0aCI6ICI8eW91ciBzZWNyZXQgaGVyZT4iCiAgICB9CiAgfQp9"
}
}
]
}
}
```
**Advantages:**
- **Native container support** - no special directives needed
- **Systemd integration** - seamless service management
- **Registry authentication** - built-in support via JSON config
- **Immutable design** - configuration applied once
#### Calamares (Hybrid Approach)
```python
# Can implement multiple patterns from Fedora analysis
class BootcInstaller:
def __init__(self, config):
self.approach = config.get("installationApproach", "systemd")
# Supports: "kickstart", "ignition", "systemd"
def run(self):
if self.approach == "kickstart":
return self.install_via_kickstart() # Fedora COSMIC Atomic pattern
elif self.approach == "ignition":
return self.install_via_ignition() # Fedora CoreOS pattern
else:
return self.install_via_systemd() # Direct systemd approach
```
**Advantages:**
- **Multiple patterns** - can use kickstart, Ignition, or systemd approaches
- **User interface** - graphical configuration for all patterns
- **Fedora compatibility** - leverages proven Fedora patterns
- **Flexible implementation** - choose best approach per use case
### 3. User Experience
#### Ignition
- **No GUI** - configuration file only
- **Technical users** - requires JSON knowledge
- **Automation-friendly** - perfect for infrastructure as code
- **Learning curve** - steep for non-technical users
#### Calamares
- **Graphical interface** - familiar installation experience
- **User-friendly** - guided configuration process
- **Progress indicators** - visual feedback
- **Error handling** - user-friendly error messages
### 4. Development Complexity
Based on Fedora pattern analysis, the complexity assessment has changed:
#### Ignition
**Implementation Requirements:**
1. **JSON generation** - create Ignition configs from user input
2. **Container integration** - systemd services for bootc installation
3. **Registry handling** - authentication and configuration
4. **Validation** - JSON schema validation
5. **Testing** - container installation workflows
**Estimated Effort:** High (3-6 months)
- Custom JSON generation logic
- Container installation integration
- Registry authentication handling
- Comprehensive testing
- **Limited Debian ecosystem support**
#### Calamares (Updated Assessment)
**Implementation Requirements:**
1. **Hybrid module** - Support kickstart, Ignition, and systemd patterns
2. **UI components** - configuration screens for all approaches
3. **Pattern integration** - leverage proven Fedora patterns
4. **Framework integration** - with existing Calamares ecosystem
5. **Testing** - comprehensive pattern testing
**Estimated Effort:** Medium (2-4 months) - **Reduced due to Fedora patterns**
- **Leverage Fedora patterns** - proven `ostreecontainer` and Ignition approaches
- **Existing framework** - Calamares module system
- **Reuse Fedora code** - adapt PyKickstart and Ignition patterns
- **Standard testing** - Calamares testing approach
- **Better Debian integration** - native ecosystem support
### 5. Debian Ecosystem Integration
#### Ignition
**Challenges:**
- **Not native to Debian** - primarily used in Fedora CoreOS
- **Limited adoption** - few Debian-based distributions use it
- **Tooling gaps** - limited Debian-specific tooling
- **Community support** - smaller Debian community
**Advantages:**
- **Modern approach** - future-proof design
- **Cloud integration** - works well with modern infrastructure
- **Immutable design** - aligns with container philosophy
#### Calamares
**Advantages:**
- **Debian native** - used in Debian and derivatives
- **Mature ecosystem** - extensive module library
- **Community support** - active Debian community
- **Documentation** - well-documented for Debian
**Challenges:**
- **Package-based focus** - originally designed for traditional installations
- **Container adaptation** - requires significant customization
- **Legacy design** - not originally container-focused
### 6. Technical Implementation
Based on Fedora analysis, both approaches can leverage proven patterns:
#### Ignition Approach (Fedora CoreOS Pattern)
```json
{
"ignition": {
"version": "3.4.0"
},
"storage": {
"disks": [disk_config],
"filesystems": [fs_config],
"files": [
{
"path": "/etc/ostree/auth.json",
"mode": 420,
"contents": {
"source": "data:text/plain;base64,{{ auth_data }}"
}
}
]
},
"systemd": {
"units": [
{
"name": "bootc-install.service",
"enabled": true,
"contents": "[Unit]\nDescription=Install bootc container\n[Service]\nType=oneshot\nExecStart=/usr/bin/bootc install to-disk /dev/sda\n[Install]\nWantedBy=multi-user.target"
}
]
}
}
```
**Implementation Steps:**
1. **Create Ignition generator** - convert user input to JSON
2. **Implement container installation** - systemd service approach
3. **Handle registry auth** - authentication configuration
4. **Add validation** - JSON schema validation
5. **Integrate with bootc** - container installation logic
#### Calamares Approach (Hybrid Pattern)
```python
# Can implement all three Fedora patterns
class HybridBootcInstaller:
def __init__(self, config):
self.approach = config.get("installationApproach", "systemd")
# Supports: "kickstart", "ignition", "systemd"
def run(self):
if self.approach == "kickstart":
return self.install_via_kickstart() # Fedora COSMIC Atomic
elif self.approach == "ignition":
return self.install_via_ignition() # Fedora CoreOS
else:
return self.install_via_systemd() # Direct approach
def install_via_kickstart(self):
# Generate ostreecontainer directive
kickstart = f"""ostreecontainer --url="{self.container_url}" \\
--stateroot="{self.stateroot}" \\
--remote="{self.remote}" \\
--transport="{self.transport}"
"""
# Execute via anaconda
subprocess.run(["anaconda", "--kickstart", "/tmp/bootc.ks"])
def install_via_ignition(self):
# Generate Ignition JSON
ignition_config = self.generate_ignition_config()
# Execute via ignition
subprocess.run(["ignition", "apply", "/tmp/bootc.ign"])
```
**Implementation Steps:**
1. **Create hybrid module** - support all Fedora patterns
2. **Design UI screens** - configuration for all approaches
3. **Implement pattern switching** - kickstart, Ignition, systemd
4. **Leverage Fedora code** - adapt PyKickstart and Ignition patterns
5. **Integrate with Calamares** - module registration and execution
### 7. Maintenance and Support
#### Ignition
**Maintenance:**
- **Custom implementation** - full control over code
- **Upstream dependencies** - Ignition specification changes
- **Container integration** - bootc compatibility
- **Testing** - comprehensive test suite needed
**Support:**
- **Limited community** - smaller Debian user base
- **Documentation** - need to create Debian-specific docs
- **Troubleshooting** - custom implementation issues
#### Calamares
**Maintenance:**
- **Framework updates** - follow Calamares development
- **Module compatibility** - ensure module works with new versions
- **Debian integration** - follow Debian packaging changes
- **Testing** - standard Calamares testing approach
**Support:**
- **Active community** - large Debian and Calamares community
- **Existing documentation** - extensive Calamares docs
- **Module ecosystem** - can leverage existing modules
### 8. Use Case Analysis
#### Ignition Best For:
- **Infrastructure automation** - GitOps, CI/CD pipelines
- **Cloud deployments** - AWS, GCP, Azure
- **Immutable infrastructure** - container-first systems
- **Technical users** - developers, system administrators
- **Large-scale deployments** - hundreds of systems
#### Calamares Best For:
- **Desktop installations** - user-friendly setup
- **Mixed environments** - traditional and container systems
- **End users** - non-technical users
- **Small to medium deployments** - individual systems
- **Debian ecosystem** - existing Debian users
### 9. Risk Assessment
#### Ignition Risks
- **High complexity** - significant development effort
- **Limited adoption** - smaller user base
- **Learning curve** - steep for users
- **Maintenance burden** - custom implementation
- **Debian integration** - potential compatibility issues
#### Calamares Risks
- **Container adaptation** - requires significant customization
- **Legacy design** - not originally container-focused
- **Framework dependency** - tied to Calamares development
- **Performance** - may be slower than Ignition
- **Complexity** - module development can be complex
### 10. Recommendation
## **Recommended Approach: Calamares with Hybrid Pattern Support**
### **Updated Reasoning (Based on Fedora Analysis):**
1. **Debian ecosystem fit** - already used in Debian
2. **User experience** - graphical interface for end users
3. **Development efficiency** - leverage existing framework + Fedora patterns
4. **Community support** - active Debian community
5. **Flexibility** - can implement kickstart, Ignition, AND systemd approaches
6. **Proven patterns** - leverage Fedora's `ostreecontainer` and Ignition implementations
7. **Future-proof** - support multiple installation paradigms
### **Enhanced Implementation Strategy:**
1. **Phase 1**: Create hybrid BootcModule supporting all Fedora patterns
2. **Phase 2**: Implement kickstart pattern (Fedora COSMIC Atomic approach)
3. **Phase 3**: Add Ignition pattern (Fedora CoreOS approach)
4. **Phase 4**: Integrate systemd direct approach
5. **Phase 5**: UI polish and comprehensive testing
### **Hybrid Pattern Benefits:**
- **Kickstart compatibility** - works with existing Fedora tooling
- **Ignition modernity** - JSON-based, cloud-native approach
- **Systemd flexibility** - direct container installation
- **User choice** - select best approach per use case
- **Fedora compatibility** - leverage proven implementations
### **Key Implementation Insights:**
- **Leverage PyKickstart** - adapt Fedora's `ostreecontainer` implementation
- **Reuse Ignition patterns** - systemd services and JSON config
- **Registry authentication** - use Fedora's `/etc/ostree/auth.json` approach
- **Modular design** - easy to add new patterns in future
## Conclusion
Based on comprehensive analysis of Fedora's kickstart and Ignition approaches, **Calamares with hybrid pattern support is the optimal choice** for our Debian bootc-image-builder project:
### **Why Calamares Wins:**
1. **Better Debian integration** - native ecosystem support
2. **Superior user experience** - graphical interface for all patterns
3. **Reduced development complexity** - leverage existing framework + Fedora patterns
4. **Active community** - better support and documentation
5. **Maximum flexibility** - support kickstart, Ignition, AND systemd approaches
6. **Proven patterns** - leverage Fedora's production implementations
7. **Future-proof** - easy to add new installation patterns
### **Key Innovation:**
The hybrid approach allows Calamares to **combine the best of all worlds**:
- **Kickstart compatibility** - works with existing Fedora tooling
- **Ignition modernity** - JSON-based, cloud-native configuration
- **Systemd flexibility** - direct container installation
- **User choice** - select optimal approach per use case
### **Implementation Advantage:**
By leveraging Fedora's proven patterns (`ostreecontainer` directive, Ignition JSON configs, systemd services), we can:
- **Reduce development time** - reuse existing, tested code
- **Ensure compatibility** - work with existing Fedora tooling
- **Provide flexibility** - support multiple installation paradigms
- **Future-proof** - easy to adapt to new patterns
The key is to implement Calamares with a **hybrid, container-first mindset**, creating a modern installation experience that bridges traditional package-based and container-based installations while leveraging the best patterns from both Fedora approaches.

206
docs/process.md Normal file
View file

@ -0,0 +1,206 @@
# Fedora bootc-image-builder Complete Workflow Analysis
## Overview
The Fedora bootc-image-builder is a sophisticated containerized tool that creates bootable disk images from bootc (bootable container) inputs. It's specifically designed for Fedora/CentOS/RHEL systems using DNF/RPM package management and supports various output formats including QCOW2, AMI, VMDK, VHD, GCE, and ISO images.
## Complete Workflow Flowchart
```mermaid
flowchart TD
A[User runs bootc-image-builder] --> B[Parse CLI Arguments]
B --> C[Validate Container Storage Mount]
C --> D[Load Configuration & Blueprint]
D --> E[Validate Container Tags]
E --> F[Get Container Size]
F --> G[Create Podman Container Instance]
G --> H[Extract OS Info from Container]
H --> I[Initialize DNF in Container]
I --> J[Create DNF Solver]
J --> K[Generate OSBuild Manifest]
K --> L[Load Distribution Definitions]
L --> M[Create Package Set Chains]
M --> N[DNF Dependency Resolution]
N --> O[Resolve Container Specs]
O --> P[Serialize Manifest]
P --> Q[Execute OSBuild Pipeline]
Q --> R{Image Type?}
R -->|Disk Images| S[Create Partition Table]
R -->|ISO Images| T[Create ISO Structure]
S --> U[Generate Filesystem Layout]
U --> V[Install GRUB2 Bootloader]
V --> W[Copy Container Contents]
W --> X[Apply Customizations]
X --> Y[Generate Final Image]
T --> Z[Create Installer Structure]
Z --> AA[Package Installer Components]
AA --> BB[Generate ISO Image]
Y --> CC{Upload to Cloud?}
BB --> CC
CC -->|Yes| DD[AWS/GCP Upload]
CC -->|No| EE[Save to Output Directory]
DD --> EE
EE --> FF[Complete]
style A fill:#e1f5fe
style FF fill:#c8e6c9
style K fill:#fff3e0
style Q fill:#f3e5f5
style R fill:#fce4ec
```
## Detailed Component Analysis
### 1. **Container Orchestration Layer**
- **Podman Container**: Manages the bootc container lifecycle
- **Container Storage**: Mounts `/var/lib/containers/storage` for image access
- **Container Inspection**: Extracts OS information, kernel details, and customization data
- **Cross-Architecture Support**: Uses qemu-user for cross-arch builds
### 2. **Package Management System**
- **DNF Solver**: Resolves package dependencies using `dnfjson.Solver`
- **RPM Metadata Cache**: Caches RPM metadata in `/rpmmd` volume
- **Librepo Backend**: Optional faster download backend
- **Repository Configuration**: Uses Fedora/CentOS/RHEL repositories
### 3. **Distribution Definition System**
- **YAML Definitions**: Loads package lists from `data/defs/*.yaml` files
- **Version Matching**: Supports exact and fuzzy version matching
- **Image Type Specific**: Different package sets for different image types
- **Multi-Directory Support**: Searches multiple definition directories
### 4. **OSBuild Integration**
- **Manifest Generation**: Creates comprehensive OSBuild manifests
- **Pipeline Definition**: Defines build, target, and export pipelines
- **Stage Management**: Orchestrates multiple build stages
- **Serialization**: Converts manifests to OSBuild-compatible format
### 5. **Image Building Pipeline**
#### **Disk Image Generation**:
1. **Partition Table Creation**: GPT/MBR partition layouts
2. **Filesystem Setup**: ext4/xfs/btrfs filesystem creation
3. **Bootloader Installation**: GRUB2 configuration and installation
4. **Container Content Copy**: Transfers bootc container contents
5. **Customization Application**: Applies user customizations
6. **Final Assembly**: Creates bootable disk image
#### **ISO Image Generation**:
1. **Installer Structure**: Creates Anaconda installer layout
2. **Package Integration**: Includes installer-specific packages
3. **Boot Configuration**: Sets up ISO boot parameters
4. **Media Creation**: Generates bootable ISO image
### 6. **Cloud Integration**
- **AWS Upload**: Direct AMI upload to AWS
- **GCP Support**: Google Cloud Platform integration
- **Multi-Region**: Support for multiple cloud regions
- **Authentication**: Handles cloud credentials and permissions
## Key Tools and Dependencies
### **Core Tools**:
- **osbuild**: Primary image building engine
- **osbuild-ostree**: OSTree integration for atomic updates
- **osbuild-depsolve-dnf**: DNF-based dependency resolution
- **osbuild-lvm2**: LVM2 support for advanced partitioning
- **podman**: Container runtime and management
- **qemu-img**: Image format conversion and manipulation
### **Package Management**:
- **dnf**: Package manager for dependency resolution
- **rpm**: Package format handling
- **librepo**: Optional high-performance download backend
- **subscription-manager**: RHEL subscription handling
### **System Components**:
- **selinux-policy-targeted**: SELinux policy enforcement
- **distribution-gpg-keys**: Package signature verification
- **qemu-user**: Cross-architecture emulation support
## Configuration System
### **Blueprint Format**:
- **TOML/JSON Configuration**: User customization files
- **Container Metadata**: Extracts configuration from container images
- **Environment Variables**: AWS credentials and other settings
- **Command-line Flags**: Extensive CLI options for fine-tuning
### **Hardcoded Defaults**:
- **Container Size Multiplier**: `containerSizeToDiskSizeMultiplier = 2`
- **Default Image Size**: `DEFAULT_SIZE = 10 * GibiByte`
- **Kernel Options**: `"rw"`, `"console=tty0"`, `"console=ttyS0"`
- **Distribution Paths**: Multiple fallback paths for definitions
## Build Process Stages
### **Stage 1: Initialization**
1. Parse CLI arguments and validate inputs
2. Mount container storage and validate access
3. Load configuration and blueprint files
4. Validate container image tags and accessibility
### **Stage 2: Container Analysis**
1. Get container size for disk sizing calculations
2. Create Podman container instance
3. Extract OS information (distro, version, kernel)
4. Initialize DNF package manager in container
5. Create DNF solver for dependency resolution
### **Stage 3: Manifest Generation**
1. Load distribution-specific package definitions
2. Create package set chains for different image types
3. Resolve package dependencies using DNF solver
4. Resolve container specifications and architectures
5. Serialize manifest for OSBuild execution
### **Stage 4: Image Building**
1. Execute OSBuild pipeline based on manifest
2. Create partition tables and filesystem layouts
3. Install bootloader and configure boot parameters
4. Copy container contents to target filesystem
5. Apply user customizations and configurations
6. Generate final bootable image
### **Stage 5: Output and Upload**
1. Save images to output directory
2. Optionally upload to cloud providers (AWS/GCP)
3. Clean up temporary files and containers
4. Report build status and results
## Supported Image Types
### **Disk Images**:
- **QCOW2**: KVM/QEMU virtual machine images
- **AMI**: Amazon Machine Images for AWS
- **VMDK**: VMware virtual machine images
- **VHD**: Microsoft Hyper-V virtual machine images
- **GCE**: Google Compute Engine images
- **Raw**: Raw disk images for direct hardware deployment
### **ISO Images**:
- **Anaconda ISO**: Fedora/CentOS/RHEL installer images
- **Custom ISO**: User-defined ISO configurations
## Architecture Support
- **x86_64**: Primary architecture
- **aarch64**: ARM64 support
- **ppc64le**: PowerPC 64-bit little-endian
- **s390x**: IBM Z architecture
- **riscv64**: RISC-V 64-bit architecture
## Testing Infrastructure
- **Python-based Tests**: Integration and functional testing
- **Go Unit Tests**: Component-level testing
- **Container Testing**: Tests run in isolated containers
- **VM Testing**: Can test resulting images in virtual machines
- **Test Plans**: FMF-based test organization and execution
This comprehensive workflow demonstrates the sophisticated orchestration of multiple tools and systems to create production-ready bootable images from container inputs, making it a powerful tool for modern container-native operating system deployment.

516
docs/simple-installer.md Normal file
View file

@ -0,0 +1,516 @@
# 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
```bash
# 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
```bash
#!/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
```bash
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
```bash
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
```bash
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
```bash
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
```bash
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
```bash
#!/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
# 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
```bash
# 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
```bash
# Boot from live CD, then:
curl -fsSL https://install.bootc.dev | sh
```
### Install Specific Container
```bash
curl -fsSL https://install.bootc.dev | sh -s -- quay.io/myorg/my-bootc:latest
```
### Install with Pre-configured Settings
```bash
# 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.