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

1125 lines
37 KiB
Markdown

# Calamares Installer Integration
## Overview
This document explores integrating Calamares installer support into the debian-bootc-image-builder project. Calamares is a modern, distribution-independent installer framework that offers a graphical interface and modular architecture, making it potentially more suitable for bootc integration than the traditional debian-installer.
## How Calamares Works: Building Installer ISOs
### Basic Concept
Calamares is **not a tool that builds ISOs directly**. Instead, it's an **installer framework** that runs on a live system (like a live CD/USB) to install the operating system to a target disk.
### Typical Workflow
1. **Create Live System**: Build a live CD/USB with your desired OS (e.g., using `live-build` for Debian)
2. **Install Calamares**: Add Calamares installer to the live system
3. **Configure Calamares**: Set up modules and configuration files
4. **Create ISO**: Package the live system with Calamares into an installer ISO
5. **User Experience**: Boot ISO → Calamares GUI runs → User installs OS to disk
### Example: Debian Live with Calamares
```bash
# 1. Create Debian live system
lb config --distribution trixie --architectures amd64
lb build
# 2. Add Calamares to the live system
# (This happens during the live-build process)
# 3. Configure Calamares modules
# Edit calamares.conf and module configs
# 4. Result: installer.iso that boots to Calamares GUI
```
### Key Points
- **Calamares runs on live system**: It's the installer that runs when you boot the ISO
- **Not an ISO builder**: You use other tools (like `live-build`) to create the ISO
- **Modular installer**: Each installation step is handled by a separate module
- **Configuration-driven**: Behavior controlled by YAML config files
### Integration with bootc-image-builder
For our project, we would:
1. **Use OSBuild** to create a live system with Calamares
2. **Configure Calamares** with a custom bootc module
3. **Generate installer ISO** that boots to Calamares GUI
4. **User installs** bootc container via Calamares interface
## Integration Architecture Options
### Option 1: Single Container (Recommended)
**Approach**: Extend the existing debian-bootc-image-builder container to support ISO generation
**Architecture**:
```
debian-bootc-image-builder container
├── OSBuild (disk images: qcow2, ami, vmdk, raw)
├── Calamares (installer ISOs: debian-installer, calamares)
├── APT integration
├── Configuration system
└── CLI interface
```
**Implementation**:
```bash
# Single container handles both disk images and installer ISOs
debian-bootc-image-builder build --type qcow2 container:latest
debian-bootc-image-builder build --type calamares container:latest
```
**Advantages**:
-**Unified interface**: Single tool for all image types
-**Shared configuration**: Same config system for all outputs
-**Simplified deployment**: One container to manage
-**Consistent UX**: Same CLI and error handling
-**Shared dependencies**: OSBuild, APT, container tools
**Challenges**:
-**Container size**: Larger container with more dependencies
-**Complexity**: More features in single container
-**Build time**: Longer build times with more components
### Option 2: Separate ISO Container
**Approach**: Create dedicated container for installer ISO generation
**Architecture**:
```
debian-bootc-image-builder container
├── OSBuild (disk images only)
├── APT integration
└── CLI interface
debian-installer-builder container
├── Calamares
├── live-build
├── ISO generation tools
└── Custom bootc module
```
**Implementation**:
```bash
# Two separate containers
debian-bootc-image-builder build --type qcow2 container:latest
debian-installer-builder build --type calamares container:latest
```
**Advantages**:
-**Focused containers**: Each container has specific purpose
-**Smaller containers**: Reduced size and complexity
-**Independent development**: Can develop features separately
-**Specialized tools**: Optimized for each use case
**Challenges**:
-**Two tools to maintain**: Separate codebases and containers
-**Configuration duplication**: Need to sync config systems
-**User confusion**: Two different tools to learn
-**Deployment complexity**: Two containers to manage
### Option 3: Hybrid Approach
**Approach**: Core container + optional ISO generation extension
**Architecture**:
```
debian-bootc-image-builder (core)
├── OSBuild (disk images)
├── APT integration
└── CLI interface
debian-bootc-image-builder:iso (extension)
├── Inherits from core
├── Calamares
├── live-build
└── ISO generation tools
```
**Implementation**:
```bash
# Core container for disk images
debian-bootc-image-builder build --type qcow2 container:latest
# Extended container for installer ISOs
debian-bootc-image-builder:iso build --type calamares container:latest
```
**Advantages**:
-**Flexible deployment**: Use core only or with ISO support
-**Shared base**: Common functionality in base container
-**Optional complexity**: ISO features only when needed
-**Incremental development**: Add ISO support later
**Challenges**:
-**Container management**: Multiple related containers
-**Version synchronization**: Keep base and extension in sync
-**Documentation complexity**: Need to document both variants
## Recommended Approach: Single Container
### Why Single Container is Best
#### 1. **Unified User Experience**
```bash
# Single tool for all image types
debian-bootc-image-builder build --type qcow2 container:latest
debian-bootc-image-builder build --type ami container:latest
debian-bootc-image-builder build --type calamares container:latest
debian-bootc-image-builder build --type debian-installer container:latest
```
#### 2. **Shared Configuration System**
```yaml
# .config/registry.yaml - works for all image types
registries:
development:
base_url: "git.raines.xyz"
namespace: "debian"
# Same config for disk images and installer ISOs
containers:
bootc_base: "{registry}/{namespace}/debian-bootc:{version}"
```
#### 3. **Consistent CLI and Error Handling**
- Same validation system for all image types
- Same progress reporting and diagnostics
- Same error messages and troubleshooting
#### 4. **Shared Dependencies**
- OSBuild (used by both disk images and live systems)
- APT integration (package resolution for both)
- Container tools (podman, etc.)
- Configuration system
### Implementation Strategy
#### Phase 1: Extend Existing Container
1. **Add Calamares dependencies** to existing Containerfile
2. **Add ISO generation tools** (live-build, etc.)
3. **Extend CLI** to support installer image types
4. **Add Calamares configuration** to existing config system
#### Phase 2: Custom Bootc Module
1. **Develop Calamares bootc module** in Python
2. **Integrate with existing** APT and container systems
3. **Test end-to-end** ISO generation and installation
#### Phase 3: Production Ready
1. **Optimize container size** (multi-stage builds, cleanup)
2. **Comprehensive testing** across all image types
3. **Documentation** for all features
### Container Structure
```dockerfile
# Containerfile
FROM debian:trixie-slim
# Base dependencies (existing)
RUN apt-get update && apt-get install -y \
podman \
qemu-utils \
apt \
systemd \
# ... existing packages
# ISO generation dependencies (new)
RUN apt-get install -y \
calamares \
live-build \
debootstrap \
# ... ISO-specific packages
# Copy application
COPY . /app
WORKDIR /app
# Single entrypoint handles all image types
ENTRYPOINT ["/app/bin/debian-bootc-image-builder"]
```
### CLI Extension
```bash
# Extended CLI supports all image types
debian-bootc-image-builder build --type qcow2 container:latest
debian-bootc-image-builder build --type ami container:latest
debian-bootc-image-builder build --type calamares container:latest
debian-bootc-image-builder build --type debian-installer container:latest
# Same validation, progress reporting, and error handling
debian-bootc-image-builder build --verbose --diagnose --type calamares container:latest
```
### Benefits of Single Container Approach
1. **Simplified Development**: One codebase, one container, one deployment
2. **Consistent UX**: Same CLI, config, and error handling for all image types
3. **Shared Infrastructure**: Leverage existing APT, OSBuild, and config systems
4. **Easier Maintenance**: Single container to update and maintain
5. **Better Testing**: Can test all image types together
6. **User-Friendly**: One tool to learn and use
### Container Size Optimization
To address the "larger container" concern:
1. **Multi-stage builds**: Separate build and runtime stages
2. **Dependency cleanup**: Remove build tools in final stage
3. **Shared base images**: Use common base for related containers
4. **Optional features**: Make ISO generation optional via build flags
This approach gives you the best of both worlds: unified user experience with the flexibility to optimize container size as needed.
## Calamares Architecture
### Core Design Principles
Calamares is designed as a **distribution-independent installer framework** with the following key characteristics:
- **Modular Architecture**: Composed of multiple modules handling different installation aspects
- **Graphical Interface**: Modern Qt-based GUI for user-friendly installation
- **Highly Customizable**: Extensive branding, theming, and configuration options
- **Distribution-Agnostic**: Works across various Linux distributions
- **Advanced Partitioning**: Both manual and automated partitioning capabilities
### Module System
Calamares uses a **modular architecture** where each installation step is handled by a separate module:
#### Core Modules
- **Partitioning**: Disk partitioning and filesystem creation
- **Users**: User account creation and configuration
- **Bootloader**: GRUB installation and configuration
- **Network**: Network configuration during installation
- **Packages**: Package installation and management
- **Services**: System service configuration
#### Custom Modules
- **Python Modules**: Easy to develop and customize
- **C++ Modules**: For performance-critical operations
- **Configuration-Driven**: Modules can be enabled/disabled via configuration
### Configuration System
Calamares uses **YAML-based configuration** files:
```yaml
# calamares.conf
modules-search: [ local ]
instances:
- id: partition
module: partition
config: partition.conf
- id: users
module: users
config: users.conf
```
## Integration Approaches
### Option 1: Custom Bootc Module (Recommended)
**Approach**: Create a custom Calamares module for bootc installation
**Advantages**:
-**Native Integration**: Built into Calamares workflow
-**User Experience**: Graphical interface for bootc installation
-**Modular Design**: Fits Calamares architecture perfectly
-**Configuration**: Can be configured via YAML
**Implementation**:
1. **Create bootc module**: Python or C++ module for bootc installation
2. **Integrate with partitioning**: Work with existing partition module
3. **Container download**: Handle container registry access
4. **Installation process**: Call `bootc install` at appropriate time
### Option 2: Package Installation Module
**Approach**: Use existing package installation module with custom packages
**Advantages**:
-**Leverage existing**: Use proven package installation
-**Simpler implementation**: Less custom code needed
**Challenges**:
-**Limited flexibility**: Harder to customize bootc installation
-**Package dependencies**: Must create bootc packages
### Option 3: Post-Installation Script
**Approach**: Use Calamares to install base system, then run bootc installation
**Advantages**:
-**Simple integration**: Minimal Calamares modification
-**Proven approach**: Similar to existing workflows
**Challenges**:
-**Two-stage process**: More complex user experience
-**Error handling**: Harder to handle bootc installation failures
## Technical Implementation
### Custom Bootc Module Development
Based on analysis of Fedora's kickstart and Ignition approaches, here's how to create a comprehensive bootc-install module for Calamares:
#### Module Structure
```python
# bootc.py - Custom Calamares module
import libcalamares
import subprocess
import json
import os
import tempfile
from pathlib import Path
def run():
"""Main module execution"""
# Get configuration from Calamares
config = libcalamares.globalstorage.value("bootcConfig")
container_url = config.get("containerUrl")
registry_auth = config.get("registryAuth", {})
install_options = config.get("installOptions", {})
# Set up registry authentication
setup_registry_auth(registry_auth)
# Download and install container
install_bootc_container(container_url, install_options)
return None
def setup_registry_auth(auth_config):
"""Set up registry authentication based on Fedora patterns"""
if not auth_config:
return
# Create /etc/ostree/auth.json (from Fedora kickstart approach)
auth_dir = Path("/etc/ostree")
auth_dir.mkdir(parents=True, exist_ok=True)
auth_data = {
"auths": auth_config.get("registries", {})
}
with open(auth_dir / "auth.json", "w") as f:
json.dump(auth_data, f, indent=2)
# Create registry configuration (from Fedora approach)
registry_dir = Path("/etc/containers/registries.conf.d")
registry_dir.mkdir(parents=True, exist_ok=True)
registry_config = ""
for registry, config in auth_config.get("registries", {}).items():
if config.get("insecure", False):
registry_config += f"[[registry]]\nlocation=\"{registry}\"\ninsecure=true\n\n"
if registry_config:
with open(registry_dir / "bootc.conf", "w") as f:
f.write(registry_config)
def install_bootc_container(container_url, install_options):
"""Install bootc container using systemd service approach"""
# Create systemd service for bootc installation (from Ignition approach)
service_content = f"""[Unit]
Description=Install bootc container
[Service]
Type=oneshot
ExecStart=/usr/bin/bootc install to-disk {install_options.get('target_disk', '/dev/sda')}
Environment=CONTAINER_URL={container_url}
[Install]
WantedBy=multi-user.target
"""
# Write service file
service_dir = Path("/etc/systemd/system")
with open(service_dir / "bootc-install.service", "w") as f:
f.write(service_content)
# Enable and start service
subprocess.run(["systemctl", "enable", "bootc-install.service"], check=True)
subprocess.run(["systemctl", "start", "bootc-install.service"], check=True)
```
#### Configuration Integration
```yaml
# bootc.conf - Based on Fedora kickstart ostreecontainer parameters
containerUrl: "quay.io/exampleos/foo:latest"
stateroot: "default"
remote: "default"
transport: "registry"
noSignatureVerification: false
# Registry authentication (from Fedora kickstart %pre sections)
registryAuth:
registries:
"quay.io":
auth: "base64-encoded-credentials"
"registry.example.com:5000":
insecure: true
# Installation options (from Fedora approaches)
installOptions:
target_disk: "/dev/sda"
target_arch: "amd64"
rootfs_type: "ext4"
bootloader: "grub"
```
#### Advanced Module Implementation
```python
# bootc_advanced.py - Comprehensive bootc module
import libcalamares
import subprocess
import json
import os
import tempfile
import shutil
from pathlib import Path
class BootcInstaller:
def __init__(self, config):
self.config = config
self.container_url = config.get("containerUrl")
self.stateroot = config.get("stateroot", "default")
self.remote = config.get("remote", self.stateroot)
self.transport = config.get("transport", "registry")
self.no_sig_verify = config.get("noSignatureVerification", False)
def run(self):
"""Main installation process"""
try:
# 1. Set up registry authentication
self.setup_registry_auth()
# 2. Configure container runtime
self.configure_container_runtime()
# 3. Install bootc container
self.install_container()
# 4. Configure bootloader for OSTree
self.configure_bootloader()
# 5. Set up system services
self.setup_system_services()
except Exception as e:
libcalamares.utils.debug(f"Bootc installation failed: {e}")
return ("Bootc installation failed", str(e))
return None
def setup_registry_auth(self):
"""Set up registry authentication using Fedora patterns"""
auth_config = self.config.get("registryAuth", {})
if not auth_config:
return
# Create /etc/ostree/auth.json (from Fedora kickstart)
auth_dir = Path("/etc/ostree")
auth_dir.mkdir(parents=True, exist_ok=True)
auth_data = {
"auths": auth_config.get("registries", {})
}
with open(auth_dir / "auth.json", "w") as f:
json.dump(auth_data, f, indent=2)
# Create registry configuration (from Fedora approach)
self.create_registry_config(auth_config)
def create_registry_config(self, auth_config):
"""Create registry configuration files"""
registry_dir = Path("/etc/containers/registries.conf.d")
registry_dir.mkdir(parents=True, exist_ok=True)
registry_config = ""
for registry, config in auth_config.get("registries", {}).items():
if config.get("insecure", False):
registry_config += f"[[registry]]\nlocation=\"{registry}\"\ninsecure=true\n\n"
if registry_config:
with open(registry_dir / "bootc.conf", "w") as f:
f.write(registry_config)
def configure_container_runtime(self):
"""Ensure container runtime is available and configured"""
# Check if podman is available
try:
subprocess.run(["podman", "--version"], check=True, capture_output=True)
except (subprocess.CalledProcessError, FileNotFoundError):
raise RuntimeError("Podman is required but not available")
# Configure container runtime for bootc
self.setup_bootc_environment()
def setup_bootc_environment(self):
"""Set up bootc environment variables and configuration"""
# Set environment variables for bootc
os.environ["CONTAINER_URL"] = self.container_url
os.environ["OSTREE_STATEROOT"] = self.stateroot
os.environ["OSTREE_REMOTE"] = self.remote
def install_container(self):
"""Install bootc container using systemd service approach"""
# Create systemd service for bootc installation (from Ignition approach)
service_content = self.generate_bootc_service()
# Write service file
service_dir = Path("/etc/systemd/system")
with open(service_dir / "bootc-install.service", "w") as f:
f.write(service_content)
# Enable and start service
subprocess.run(["systemctl", "daemon-reload"], check=True)
subprocess.run(["systemctl", "enable", "bootc-install.service"], check=True)
subprocess.run(["systemctl", "start", "bootc-install.service"], check=True)
def generate_bootc_service(self):
"""Generate systemd service for bootc installation"""
target_disk = self.config.get("installOptions", {}).get("target_disk", "/dev/sda")
service_content = f"""[Unit]
Description=Install bootc container
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/bootc install to-disk {target_disk}
Environment=CONTAINER_URL={self.container_url}
Environment=OSTREE_STATEROOT={self.stateroot}
Environment=OSTREE_REMOTE={self.remote}
Environment=OSTREE_TRANSPORT={self.transport}
"""
if self.no_sig_verify:
service_content += "Environment=OSTREE_NO_SIGNATURE_VERIFICATION=1\n"
service_content += """
[Install]
WantedBy=multi-user.target
"""
return service_content
def configure_bootloader(self):
"""Configure bootloader for OSTree-based bootc system"""
# This would integrate with Calamares bootloader module
# to ensure GRUB is configured for OSTree deployments
bootloader_config = {
"ostree_enabled": True,
"stateroot": self.stateroot,
"remote": self.remote
}
# Store configuration for bootloader module
libcalamares.globalstorage.insert("bootcBootloaderConfig", bootloader_config)
def setup_system_services(self):
"""Set up system services for bootc"""
# Enable bootc-related services
services = [
"bootc-update.service",
"bootc-update.path"
]
for service in services:
try:
subprocess.run(["systemctl", "enable", service], check=True)
except subprocess.CalledProcessError:
# Service might not exist yet, that's okay
pass
def run():
"""Main module execution"""
config = libcalamares.globalstorage.value("bootcConfig")
installer = BootcInstaller(config)
return installer.run()
```
#### Calamares Integration Configuration
```yaml
# calamares.conf - Main configuration
modules-search: [ local ]
instances:
- id: partition
module: partition
config: partition.conf
- id: bootc
module: bootc
config: bootc.conf
- id: bootloader
module: bootloader
config: bootloader.conf
```
#### Bootc Module Configuration
```yaml
# bootc.conf - Comprehensive configuration
# Based on Fedora ostreecontainer directive parameters
containerUrl: "{{ registry }}/{{ namespace }}/{{ image }}:{{ tag }}"
stateroot: "default"
remote: "default"
transport: "registry"
noSignatureVerification: false
# Registry authentication (from Fedora kickstart %pre sections)
registryAuth:
registries:
"quay.io":
auth: "{{ base64_encoded_credentials }}"
"registry.example.com:5000":
insecure: true
# Installation options
installOptions:
target_disk: "/dev/sda"
target_arch: "amd64"
rootfs_type: "ext4"
bootloader: "grub"
# Integration with other modules
integration:
partition_module: "partition"
bootloader_module: "bootloader"
network_module: "network"
```
#### Integration with Existing Modules
- **Partitioning**: Coordinate with partition module for disk layout
- **Bootloader**: Ensure GRUB is configured for OSTree
- **Users**: Handle user creation in bootc environment
### Hybrid Approach: Kickstart + Ignition Patterns
Based on the analysis of both Fedora approaches, we can create a hybrid Calamares module that combines the best of both:
#### Kickstart Pattern Integration
```python
def generate_kickstart_config(self):
"""Generate kickstart configuration for bootc installation"""
# Based on Fedora ostreecontainer directive
kickstart_content = f"""# Bootc installation kickstart
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="{self.container_url}" \\
--stateroot="{self.stateroot}" \\
--remote="{self.remote}" \\
--transport="{self.transport}"
"""
if self.no_sig_verify:
kickstart_content += " --no-signature-verification\n"
kickstart_content += """
# System configuration
firewall --disabled
services --enabled=sshd
rootpw --iscrypted locked
reboot
"""
return kickstart_content
```
#### Ignition Pattern Integration
```python
def generate_ignition_config(self):
"""Generate Ignition configuration for bootc installation"""
# Based on Fedora CoreOS Ignition approach
ignition_config = {
"ignition": {
"version": "3.4.0"
},
"storage": {
"disks": self.get_disk_config(),
"filesystems": self.get_filesystem_config(),
"files": self.get_auth_files()
},
"systemd": {
"units": [
{
"name": "bootc-install.service",
"enabled": True,
"contents": self.generate_bootc_service()
}
]
},
"networkd": {
"units": self.get_network_config()
}
}
return ignition_config
def get_auth_files(self):
"""Generate authentication files (from Fedora patterns)"""
files = []
# Registry authentication
if self.config.get("registryAuth"):
auth_data = {
"auths": self.config["registryAuth"].get("registries", {})
}
files.append({
"path": "/etc/ostree/auth.json",
"mode": 420,
"contents": {
"source": f"data:text/plain;base64,{base64.b64encode(json.dumps(auth_data).encode()).decode()}"
}
})
return files
```
#### Combined Implementation Strategy
```python
class HybridBootcInstaller:
def __init__(self, config):
self.config = config
self.approach = config.get("installationApproach", "systemd") # "kickstart", "ignition", "systemd"
def run(self):
"""Main installation process using hybrid approach"""
if self.approach == "kickstart":
return self.install_via_kickstart()
elif self.approach == "ignition":
return self.install_via_ignition()
else: # systemd (default)
return self.install_via_systemd()
def install_via_kickstart(self):
"""Install using kickstart approach (Fedora COSMIC Atomic pattern)"""
# Generate kickstart file
kickstart_content = self.generate_kickstart_config()
# Write kickstart file
kickstart_path = "/tmp/bootc.ks"
with open(kickstart_path, "w") as f:
f.write(kickstart_content)
# Execute kickstart installation
subprocess.run(["anaconda", "--kickstart", kickstart_path], check=True)
def install_via_ignition(self):
"""Install using Ignition approach (Fedora CoreOS pattern)"""
# Generate Ignition config
ignition_config = self.generate_ignition_config()
# Write Ignition file
ignition_path = "/tmp/bootc.ign"
with open(ignition_path, "w") as f:
json.dump(ignition_config, f, indent=2)
# Execute Ignition installation
subprocess.run(["ignition", "apply", ignition_path], check=True)
def install_via_systemd(self):
"""Install using systemd service approach (recommended)"""
# This is the approach we implemented above
return self.install_container()
```
### Configuration for Hybrid Approach
```yaml
# bootc.conf - Hybrid configuration
# Choose installation approach
installationApproach: "systemd" # "kickstart", "ignition", "systemd"
# Container configuration (from Fedora ostreecontainer)
containerUrl: "quay.io/exampleos/foo:latest"
stateroot: "default"
remote: "default"
transport: "registry"
noSignatureVerification: false
# Registry authentication (from both Fedora approaches)
registryAuth:
registries:
"quay.io":
auth: "base64-encoded-credentials"
"registry.example.com:5000":
insecure: true
# Installation options
installOptions:
target_disk: "/dev/sda"
target_arch: "amd64"
rootfs_type: "ext4"
bootloader: "grub"
# Approach-specific options
kickstartOptions:
network_config: "dhcp"
partitioning: "autopart"
services: ["sshd"]
ignitionOptions:
version: "3.4.0"
network_units: ["00-eth0.network"]
additional_units: []
```
- **Network**: Manage network access for container download
### Calamares Configuration
#### Main Configuration
```yaml
# calamares.conf
modules-search: [ local ]
instances:
- id: partition
module: partition
config: partition.conf
- id: bootc
module: bootc
config: bootc.conf
- id: bootloader
module: bootloader
config: bootloader.conf
```
#### Bootc-Specific Configuration
```yaml
# bootc.conf
containerUrl: "{{ registry }}/{{ namespace }}/{{ image }}:{{ tag }}"
downloadPath: "/tmp/bootc-container"
installOptions:
targetArch: "amd64"
rootfsType: "ext4"
bootloader: "grub"
```
## Advantages Over Debian-Installer
### 1. Modern Architecture
- **Graphical Interface**: User-friendly installation experience
- **Modular Design**: Easy to extend and customize
- **Configuration-Driven**: Flexible configuration system
### 2. Better Integration Potential
- **Custom Modules**: Can create bootc-specific installation module
- **Python Support**: Easier to develop custom functionality
- **Active Development**: Modern, actively maintained project
### 3. User Experience
- **Intuitive Interface**: Modern GUI vs. text-based installer
- **Progress Feedback**: Clear installation progress indication
- **Error Handling**: Better error reporting and recovery
### 4. Technical Benefits
- **Distribution-Agnostic**: Not tied to specific Debian internals
- **Extensible**: Easy to add new features and modules
- **Well-Documented**: Comprehensive documentation and examples
## Technical Challenges
### 1. Module Development Complexity
**Challenge**: Creating a custom bootc module requires significant development
- **Learning Curve**: Understanding Calamares module architecture
- **Integration Points**: Coordinating with existing modules
- **Error Handling**: Robust error handling and recovery
**Mitigation**:
- **Start Simple**: Begin with basic module and iterate
- **Leverage Examples**: Use existing modules as templates
- **Community Support**: Calamares has active community
### 2. Container Download and Storage
**Challenge**: Managing container downloads during installation
- **Network Access**: Ensuring network connectivity
- **Storage Space**: Temporary storage for container images
- **Authentication**: Registry authentication handling
**Solutions**:
- **Pre-download**: Download container before installation starts
- **Streaming**: Stream container directly to installation target
- **Caching**: Cache containers for offline installations
### 3. Bootloader Configuration
**Challenge**: Configuring GRUB for OSTree-based bootc systems
- **OSTree Integration**: GRUB must understand OSTree deployments
- **Kernel Parameters**: Special parameters for bootc systems
- **UEFI/BIOS Support**: Different bootloader requirements
**Approach**:
- **Custom Bootloader Module**: Extend existing bootloader module
- **OSTree Support**: Add OSTree-specific GRUB configuration
- **Testing**: Comprehensive testing across different hardware
### 4. Package Management Integration
**Challenge**: Integrating with existing package management
- **Dependency Resolution**: Ensuring bootc dependencies are met
- **Package Installation**: Installing bootc and related packages
- **Repository Management**: Managing package repositories
**Solution**:
- **Hybrid Approach**: Use Calamares for base system, bootc for container
- **Package Module**: Leverage existing package installation module
- **Custom Packages**: Create bootc-specific packages if needed
## Implementation Strategy
Based on the analysis of Fedora's kickstart and Ignition approaches, here's a comprehensive implementation roadmap:
### Phase 1: Foundation and Research
1. **Study Fedora Patterns**: Analyze `ostreecontainer` directive and Ignition configs
2. **Calamares Architecture**: Understand module system and configuration
3. **Container Runtime**: Ensure podman/containerd integration
4. **Registry Authentication**: Implement Fedora-style auth patterns
### Phase 2: Core Module Development
1. **Basic Bootc Module**: Create simple Python module for bootc installation
2. **Registry Integration**: Implement `/etc/ostree/auth.json` and registry config
3. **Systemd Service**: Create bootc installation service (Ignition pattern)
4. **Configuration System**: Integrate with existing debian-bootc-image-builder config
### Phase 3: Advanced Features
1. **Hybrid Approach**: Support kickstart, Ignition, and systemd patterns
2. **Partitioning Integration**: Coordinate with Calamares partition module
3. **Bootloader Configuration**: Configure GRUB for OSTree deployments
4. **Error Handling**: Robust error handling and user feedback
### Phase 4: Production Ready
1. **User Interface**: Polish Calamares UI for bootc configuration
2. **Testing**: Comprehensive testing across all patterns
3. **Documentation**: User and developer documentation
4. **Integration**: Full integration with debian-bootc-image-builder
### Implementation Details
#### Module Development Steps
```python
# 1. Basic module structure
class BootcModule:
def __init__(self):
self.config = None
self.container_url = None
self.registry_auth = None
def run(self):
# Main installation logic
pass
# 2. Registry authentication (from Fedora kickstart)
def setup_registry_auth(self):
# Create /etc/ostree/auth.json
# Create /etc/containers/registries.conf.d/bootc.conf
pass
# 3. Container installation (from Fedora Ignition)
def install_container(self):
# Create systemd service
# Execute bootc install
pass
# 4. Integration with Calamares
def integrate_with_calamares(self):
# Coordinate with partition module
# Configure bootloader module
# Handle user creation
pass
```
#### Testing Strategy
1. **Unit Tests**: Test individual module functions
2. **Integration Tests**: Test with Calamares framework
3. **End-to-End Tests**: Test complete installation process
4. **Pattern Tests**: Test kickstart, Ignition, and systemd approaches
#### Configuration Integration
```yaml
# Integration with existing debian-bootc-image-builder config
# .config/registry.yaml
calamares:
enabled: true
installation_approach: "systemd" # "kickstart", "ignition", "systemd"
container_config:
stateroot: "default"
remote: "default"
transport: "registry"
registry_auth:
# Same as existing registry config
```
### Key Implementation Insights
#### From Fedora Kickstart Analysis:
- **`ostreecontainer` directive** provides complete parameter set
- **Registry authentication** via `/etc/ostree/auth.json`
- **No `%packages` section** - container-first approach
- **Dracut hooks** for kickstart processing
#### From Fedora Ignition Analysis:
- **Systemd services** for container installation
- **JSON-based configuration** - easier to generate
- **Modular approach** - can combine different config sources
- **Immutable design** - configuration applied once
#### Hybrid Benefits:
- **Flexibility**: Support multiple installation patterns
- **Compatibility**: Work with existing Fedora tooling
- **Modern approach**: Leverage best of both worlds
- **Future-proof**: Easy to extend and modify
## Comparison: Calamares vs Debian-Installer
| Aspect | Calamares | Debian-Installer |
|--------|-----------|------------------|
| **Interface** | Graphical (Qt) | Text-based |
| **Architecture** | Modular | Monolithic |
| **Customization** | High (modules) | Low (preseed) |
| **Development** | Python/C++ | C/Shell scripts |
| **Documentation** | Comprehensive | Limited |
| **Community** | Active | Established |
| **Bootc Integration** | Custom module | Preseed hooks |
| **User Experience** | Modern | Traditional |
| **Complexity** | Medium | High |
## Recommendation
**Use Calamares with Custom Bootc Module**:
### Advantages
-**Modern Architecture**: Modular, extensible design
-**Better UX**: Graphical interface and better error handling
-**Easier Development**: Python modules and good documentation
-**Active Community**: Ongoing development and support
-**Distribution-Agnostic**: Not tied to Debian internals
### Implementation Approach
1. **Create Custom Module**: Develop bootc installation module
2. **Integrate with Existing**: Work with partition and bootloader modules
3. **Configuration System**: Extend existing config system
4. **User Experience**: Provide modern, intuitive installation
### Risk Mitigation
- **Start Simple**: Begin with basic functionality
- **Leverage Community**: Use existing modules and documentation
- **Iterative Development**: Build and test incrementally
- **Fallback Option**: Keep debian-installer as backup
## Next Steps
1. **Research Calamares Module Development**: Study existing modules and architecture
2. **Create Bootc Module Prototype**: Develop basic bootc installation module
3. **Test Calamares Integration**: Verify module integration and functionality
4. **Design Configuration System**: Plan integration with existing config system
5. **Evaluate Complexity**: Assess development effort vs. benefits
6. **Compare with Debian-Installer**: Make final decision on approach