1125 lines
37 KiB
Markdown
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
|