Initial commit: Comprehensive Debian bootc documentation
- Complete documentation for all bootc commands and subcommands - Debian-specific adaptations and workarounds - Manual installation methods to bypass bootc reliability issues - Technical guides with Rust source code analysis - Flowcharts and external command references - Hidden command documentation (bootc internals, state, etc.) - Composefs integration analysis - Base image creation guides (with and without bootc binary) - Management scripts and automation - Comprehensive troubleshooting and examples
This commit is contained in:
commit
526f1c1afd
67 changed files with 34174 additions and 0 deletions
422
install/external-commands-reference.md
Normal file
422
install/external-commands-reference.md
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
# bootc External Commands Reference
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides a comprehensive reference for all external commands used by bootc during the installation process. These commands are executed by bootc to perform various system operations that cannot be handled internally.
|
||||
|
||||
## Required Commands
|
||||
|
||||
### 1. ostree - OSTree Repository Management
|
||||
|
||||
**Purpose**: Manages OSTree repositories for atomic updates and deployments
|
||||
|
||||
**Package**: `ostree`
|
||||
|
||||
**Key Commands Used**:
|
||||
|
||||
```bash
|
||||
# Initialize OSTree filesystem
|
||||
ostree admin init-fs --modern .
|
||||
|
||||
# Configure repository settings
|
||||
ostree config --repo ostree/repo set sysroot.bootloader none
|
||||
ostree config --repo ostree/repo set sysroot.bootprefix true
|
||||
ostree config --repo ostree/repo set sysroot.readonly true
|
||||
|
||||
# Parse commit information
|
||||
ostree --repo=/ostree/repo rev-parse --single
|
||||
|
||||
# Read commit metadata
|
||||
ostree read-commit <commit-hash>
|
||||
```
|
||||
|
||||
**Configuration Files**:
|
||||
- Repository config: `ostree/repo/config`
|
||||
- Deployment config: `ostree/deploy/*/var/lib/ostree/config`
|
||||
|
||||
**Error Handling**:
|
||||
- Repository corruption detection
|
||||
- Commit validation
|
||||
- Configuration validation
|
||||
|
||||
### 2. bootupd - Bootloader Management
|
||||
|
||||
**Purpose**: Manages bootloader installation and configuration
|
||||
|
||||
**Package**: `bootupd`
|
||||
|
||||
**Key Commands Used**:
|
||||
|
||||
```bash
|
||||
# Install bootloader
|
||||
bootupctl install
|
||||
|
||||
# Generate bootloader configuration
|
||||
bootupctl generate
|
||||
|
||||
# Check bootloader status
|
||||
bootupctl status
|
||||
|
||||
# Update bootloader
|
||||
bootupctl update
|
||||
```
|
||||
|
||||
**Configuration Files**:
|
||||
- Bootloader state: `/boot/bootupd-state.json`
|
||||
- GRUB config: `/boot/grub2/grub.cfg`
|
||||
- EFI config: `/boot/efi/EFI/*/grub.cfg`
|
||||
|
||||
**Architecture Support**:
|
||||
- x86_64: GRUB2
|
||||
- aarch64: GRUB2
|
||||
- s390x: zipl (via separate implementation)
|
||||
|
||||
### 3. podman - Container Runtime
|
||||
|
||||
**Purpose**: Container runtime for running bootc installation
|
||||
|
||||
**Package**: `podman`
|
||||
|
||||
**Required Flags**:
|
||||
```bash
|
||||
podman run --rm --privileged --pid=host \
|
||||
-v /var/lib/containers:/var/lib/containers \
|
||||
-v /dev:/dev \
|
||||
--security-opt label=type:unconfined_t \
|
||||
<image> bootc install to-disk /dev/target
|
||||
```
|
||||
|
||||
**Container Environment Variables**:
|
||||
- `CONTAINER_ENGINE=podman`
|
||||
- `CONTAINER_IMAGE_ID=<image-id>`
|
||||
- `CONTAINER_IMAGE=<image-name>`
|
||||
- `CONTAINER_ROOTLESS=<0|1>`
|
||||
|
||||
### 4. Filesystem Management Commands
|
||||
|
||||
#### fstrim - Filesystem Optimization
|
||||
|
||||
**Purpose**: Trim filesystem to optimize performance
|
||||
|
||||
**Package**: `util-linux`
|
||||
|
||||
**Command Used**:
|
||||
```bash
|
||||
fstrim --quiet-unsupported -v /target
|
||||
```
|
||||
|
||||
**Options**:
|
||||
- `--quiet-unsupported`: Suppress errors for unsupported filesystems
|
||||
- `-v`: Verbose output
|
||||
|
||||
#### mount/umount - Filesystem Mounting
|
||||
|
||||
**Purpose**: Mount and unmount filesystems
|
||||
|
||||
**Package**: `util-linux`
|
||||
|
||||
**Commands Used**:
|
||||
```bash
|
||||
# Mount filesystem
|
||||
mount /dev/target /mnt
|
||||
|
||||
# Remount read-only
|
||||
mount -o remount,ro /target
|
||||
|
||||
# Unmount filesystem
|
||||
umount -R /target
|
||||
```
|
||||
|
||||
#### fsfreeze - Filesystem Freeze/Thaw
|
||||
|
||||
**Purpose**: Freeze and thaw filesystems for consistency
|
||||
|
||||
**Package**: `util-linux`
|
||||
|
||||
**Commands Used**:
|
||||
```bash
|
||||
# Freeze filesystem
|
||||
fsfreeze -f /target
|
||||
|
||||
# Thaw filesystem
|
||||
fsfreeze -u /target
|
||||
```
|
||||
|
||||
## Optional Commands
|
||||
|
||||
### 1. cryptsetup - LUKS Encryption
|
||||
|
||||
**Purpose**: Handle LUKS encrypted devices
|
||||
|
||||
**Package**: `cryptsetup`
|
||||
|
||||
**Commands Used**:
|
||||
```bash
|
||||
# Close LUKS device
|
||||
cryptsetup close <device-name>
|
||||
|
||||
# Open LUKS device
|
||||
cryptsetup open <device> <name>
|
||||
|
||||
# Create LUKS device
|
||||
cryptsetup luksFormat <device>
|
||||
```
|
||||
|
||||
**Integration**:
|
||||
- TPM2-LUKS support via systemd-cryptenroll
|
||||
- LUKS device detection and management
|
||||
- Encryption key handling
|
||||
|
||||
### 2. grub2-mkconfig - GRUB Configuration
|
||||
|
||||
**Purpose**: Generate GRUB configuration files
|
||||
|
||||
**Package**: `grub2-tools`
|
||||
|
||||
**Commands Used**:
|
||||
```bash
|
||||
# Generate GRUB configuration
|
||||
grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
|
||||
# Generate EFI configuration
|
||||
grub2-mkconfig -o /boot/efi/EFI/*/grub.cfg
|
||||
```
|
||||
|
||||
**Configuration Files**:
|
||||
- GRUB config: `/etc/default/grub`
|
||||
- GRUB scripts: `/etc/grub.d/*`
|
||||
- Generated config: `/boot/grub2/grub.cfg`
|
||||
|
||||
### 3. dracut - Initramfs Generation
|
||||
|
||||
**Purpose**: Generate initramfs for boot
|
||||
|
||||
**Package**: `dracut`
|
||||
|
||||
**Commands Used**:
|
||||
```bash
|
||||
# Generate initramfs
|
||||
dracut --force /boot/initramfs-<version>.img <version>
|
||||
|
||||
# Regenerate with specific modules
|
||||
dracut --add-drivers <modules> --force
|
||||
```
|
||||
|
||||
**Integration**:
|
||||
- Initramfs generation during container build
|
||||
- Module detection and inclusion
|
||||
- Boot-time filesystem setup
|
||||
|
||||
### 4. Filesystem Creation Commands
|
||||
|
||||
#### mkfs.* - Filesystem Creation
|
||||
|
||||
**Purpose**: Create various filesystem types
|
||||
|
||||
**Package**: `util-linux`, `e2fsprogs`, `xfsprogs`, `btrfs-progs`
|
||||
|
||||
**Commands Used**:
|
||||
```bash
|
||||
# Create XFS filesystem
|
||||
mkfs.xfs /dev/target
|
||||
|
||||
# Create ext4 filesystem
|
||||
mkfs.ext4 /dev/target
|
||||
|
||||
# Create Btrfs filesystem
|
||||
mkfs.btrfs /dev/target
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
- Filesystem type determined by install config
|
||||
- Default type: XFS
|
||||
- Configurable via `/usr/lib/bootc/install/*.toml`
|
||||
|
||||
## Command Execution Patterns
|
||||
|
||||
### 1. Task Execution
|
||||
|
||||
```rust
|
||||
// From install.rs - Task execution pattern
|
||||
Task::new("Operation description", "command")
|
||||
.args(["arg1", "arg2"])
|
||||
.cwd(target_directory)?
|
||||
.run()?;
|
||||
```
|
||||
|
||||
### 2. Command with Capture
|
||||
|
||||
```rust
|
||||
// From install.rs - Command with stderr capture
|
||||
Command::new("command")
|
||||
.args(["arg1", "arg2"])
|
||||
.cwd_dir(target_directory)
|
||||
.run_capture_stderr()?;
|
||||
```
|
||||
|
||||
### 3. Async Command Execution
|
||||
|
||||
```rust
|
||||
// From install.rs - Async command execution
|
||||
let result = tokio::task::spawn_blocking(move || {
|
||||
Command::new("command")
|
||||
.args(["arg1", "arg2"])
|
||||
.run()
|
||||
}).await??;
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 1. Command Not Found
|
||||
|
||||
**Detection**: Process exit code 127
|
||||
**Handling**: Check package installation
|
||||
**Recovery**: Install required package
|
||||
|
||||
### 2. Permission Denied
|
||||
|
||||
**Detection**: Process exit code 13
|
||||
**Handling**: Check user privileges
|
||||
**Recovery**: Run with appropriate privileges
|
||||
|
||||
### 3. Resource Exhaustion
|
||||
|
||||
**Detection**: Process exit code 28
|
||||
**Handling**: Check disk space, memory
|
||||
**Recovery**: Free up resources
|
||||
|
||||
### 4. Filesystem Errors
|
||||
|
||||
**Detection**: Process exit code 1
|
||||
**Handling**: Check filesystem state
|
||||
**Recovery**: Repair filesystem if possible
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### 1. Command Injection Prevention
|
||||
|
||||
- All commands use structured arguments
|
||||
- No shell interpretation
|
||||
- Input validation and sanitization
|
||||
|
||||
### 2. Privilege Escalation
|
||||
|
||||
- Commands run with minimal required privileges
|
||||
- SELinux context preservation
|
||||
- Capability dropping where possible
|
||||
|
||||
### 3. Resource Limits
|
||||
|
||||
- Disk space validation before operations
|
||||
- Memory usage monitoring
|
||||
- File descriptor limits
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### 1. Parallel Execution
|
||||
|
||||
- Independent commands run in parallel
|
||||
- I/O operations optimized
|
||||
- Resource usage balanced
|
||||
|
||||
### 2. Caching
|
||||
|
||||
- OSTree repository caching
|
||||
- Container image layer caching
|
||||
- Configuration caching
|
||||
|
||||
### 3. Resource Management
|
||||
|
||||
- Temporary file cleanup
|
||||
- Memory usage optimization
|
||||
- Disk I/O optimization
|
||||
|
||||
## Debugging Commands
|
||||
|
||||
### 1. System Information
|
||||
|
||||
```bash
|
||||
# Check OSTree status
|
||||
ostree admin status
|
||||
|
||||
# Check bootloader status
|
||||
bootupctl status
|
||||
|
||||
# Check filesystem usage
|
||||
df -h
|
||||
|
||||
# Check mounted filesystems
|
||||
mount | grep -E "(ostree|boot)"
|
||||
```
|
||||
|
||||
### 2. Container Information
|
||||
|
||||
```bash
|
||||
# List container images
|
||||
podman images
|
||||
|
||||
# Check container storage
|
||||
podman system df
|
||||
|
||||
# Inspect container image
|
||||
podman inspect <image>
|
||||
```
|
||||
|
||||
### 3. Boot Information
|
||||
|
||||
```bash
|
||||
# Check kernel command line
|
||||
cat /proc/cmdline
|
||||
|
||||
# Check bootloader entries
|
||||
ls /boot/loader/entries/
|
||||
|
||||
# Check EFI variables
|
||||
efibootmgr -v
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### 1. Common Issues
|
||||
|
||||
**OSTree Repository Corruption**:
|
||||
```bash
|
||||
# Repair repository
|
||||
ostree admin init-fs --modern .
|
||||
```
|
||||
|
||||
**Bootloader Installation Failure**:
|
||||
```bash
|
||||
# Reinstall bootloader
|
||||
bootupctl install --force
|
||||
```
|
||||
|
||||
**Filesystem Mount Issues**:
|
||||
```bash
|
||||
# Check mount options
|
||||
mount | grep <device>
|
||||
# Remount with correct options
|
||||
mount -o remount,<options> <device>
|
||||
```
|
||||
|
||||
### 2. Log Analysis
|
||||
|
||||
**Systemd Journal**:
|
||||
```bash
|
||||
# Check bootc logs
|
||||
journalctl -u bootc*
|
||||
|
||||
# Check installation logs
|
||||
journalctl -f | grep bootc
|
||||
```
|
||||
|
||||
**OSTree Logs**:
|
||||
```bash
|
||||
# Check OSTree operations
|
||||
journalctl -u ostree*
|
||||
|
||||
# Check repository operations
|
||||
ostree log <commit>
|
||||
```
|
||||
|
||||
This reference provides comprehensive information about all external commands used by bootc, their purposes, usage patterns, and troubleshooting approaches.
|
||||
282
install/installation-flowchart.md
Normal file
282
install/installation-flowchart.md
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
# bootc Installation Process Flowchart
|
||||
|
||||
## High-Level Installation Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ bootc Installation Process │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Phase 1: Preparation │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 1.1 Container Environment Detection │
|
||||
│ ├─ Check podman runtime │
|
||||
│ ├─ Validate container execution info │
|
||||
│ └─ Verify privileged access │
|
||||
│ │
|
||||
│ 1.2 Privilege and Namespace Validation │
|
||||
│ ├─ Require --pid=host flag │
|
||||
│ ├─ Validate host user namespace │
|
||||
│ └─ Check root privileges │
|
||||
│ │
|
||||
│ 1.3 SELinux State Management │
|
||||
│ ├─ Detect SELinux policy in container │
|
||||
│ ├─ Check host SELinux state │
|
||||
│ └─ Re-execute if needed for proper labeling │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Phase 2: Filesystem Setup │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 2.1 OSTree Repository Initialization │
|
||||
│ ├─ Check for existing ostree/repo │
|
||||
│ ├─ Run: ostree admin init-fs --modern . │
|
||||
│ ├─ Configure repository settings │
|
||||
│ └─ Set up stateroot │
|
||||
│ │
|
||||
│ 2.2 Container Image Deployment │
|
||||
│ ├─ Prepare container image for pull │
|
||||
│ ├─ Check disk space requirements │
|
||||
│ ├─ Pull image into OSTree repository │
|
||||
│ ├─ Deploy container to target filesystem │
|
||||
│ └─ Set up deployment metadata │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Phase 3: Bootloader Setup │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 3.1 Bootupd Integration │
|
||||
│ ├─ Detect target architecture │
|
||||
│ ├─ Configure bootloader type │
|
||||
│ └─ Install via bootupd │
|
||||
│ │
|
||||
│ 3.2 Architecture-Specific Bootloaders │
|
||||
│ ├─ x86_64/aarch64: GRUB2 via bootupd │
|
||||
│ ├─ s390x: zipl │
|
||||
│ └─ Other: Platform-specific │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Phase 4: Kernel Configuration │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 4.1 Kernel Argument Processing │
|
||||
│ ├─ Extract kargs from OSTree root │
|
||||
│ ├─ Merge install config kargs │
|
||||
│ ├─ Apply container image kargs.d │
|
||||
│ └─ Add CLI-specified kargs │
|
||||
│ │
|
||||
│ 4.2 Initramfs Integration │
|
||||
│ ├─ Locate kernel: /usr/lib/modules/$kver/vmlinuz │
|
||||
│ ├─ Locate initramfs: /usr/lib/modules/$kver/initramfs.img │
|
||||
│ └─ Configure bootloader entries │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Phase 5: Finalization │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 5.1 Filesystem Optimization │
|
||||
│ ├─ Run: fstrim --quiet-unsupported -v /target │
|
||||
│ ├─ Run: mount -o remount,ro /target │
|
||||
│ └─ Run: fsfreeze -f /target && fsfreeze -u /target │
|
||||
│ │
|
||||
│ 5.2 Cleanup and Validation │
|
||||
│ ├─ Close file descriptors │
|
||||
│ ├─ Unmount target filesystem │
|
||||
│ ├─ Close LUKS devices (if any) │
|
||||
│ └─ Validate installation │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Installation Complete │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Detailed Installation Modes
|
||||
|
||||
### 1. to-disk Installation Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ bootc install to-disk │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Validate Target Device │
|
||||
│ ├─ Check if device is block device or file │
|
||||
│ ├─ Handle loopback device if --via-loopback │
|
||||
│ └─ Validate device permissions │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. Create Filesystem │
|
||||
│ ├─ Determine filesystem type from config │
|
||||
│ ├─ Run: mkfs.$fstype /dev/target │
|
||||
│ └─ Set up partition table if needed │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Mount and Deploy │
|
||||
│ ├─ Mount: /dev/target /mnt │
|
||||
│ ├─ Run: bootc install to-filesystem /mnt │
|
||||
│ └─ Configure kernel arguments │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. Finalize │
|
||||
│ ├─ Unmount: umount -R /mnt │
|
||||
│ ├─ Close LUKS devices │
|
||||
│ └─ Close loopback devices │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. to-filesystem Installation Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ bootc install to-filesystem │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Validate Target Filesystem │
|
||||
│ ├─ Check if target is directory │
|
||||
│ ├─ Verify it's a mountpoint │
|
||||
│ ├─ Detect if already OSTree system │
|
||||
│ └─ Handle alongside installation │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. Clean Target (if needed) │
|
||||
│ ├─ Wipe mode: Remove all contents │
|
||||
│ ├─ Alongside mode: Clean boot directories │
|
||||
│ └─ Default: Require empty root directory │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Deploy Container Image │
|
||||
│ ├─ Initialize OSTree repository │
|
||||
│ ├─ Pull container image │
|
||||
│ ├─ Deploy to target filesystem │
|
||||
│ └─ Configure bootloader │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. Finalize │
|
||||
│ ├─ Run: bootc install finalize │
|
||||
│ ├─ Optimize filesystem │
|
||||
│ └─ Validate installation │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3. to-existing-root Installation Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ bootc install to-existing-root │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Mount Host Root │
|
||||
│ ├─ Mount: /:/target (if not already mounted) │
|
||||
│ ├─ Detect existing OSTree system │
|
||||
│ └─ Find physical root in /sysroot │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. Clean Boot Directories │
|
||||
│ ├─ Remove existing bootloader configuration │
|
||||
│ ├─ Clean /boot directory │
|
||||
│ └─ Clean /boot/efi directory (if exists) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Deploy Alongside │
|
||||
│ ├─ Initialize OSTree repository │
|
||||
│ ├─ Deploy container image │
|
||||
│ ├─ Configure bootloader │
|
||||
│ └─ Set up cleanup service │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. Setup Cleanup │
|
||||
│ ├─ Create bootc-destructive-cleanup.service │
|
||||
│ ├─ Configure for first boot cleanup │
|
||||
│ └─ Preserve existing data in /sysroot │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Error Handling Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Error Detection │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Validation Errors │
|
||||
│ ├─ Container environment issues │
|
||||
│ ├─ Privilege/permission errors │
|
||||
│ └─ SELinux policy conflicts │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. Resource Errors │
|
||||
│ ├─ Insufficient disk space │
|
||||
│ ├─ Memory allocation failures │
|
||||
│ └─ File descriptor limits │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Deployment Errors │
|
||||
│ ├─ Container image pull failures │
|
||||
│ ├─ OSTree repository issues │
|
||||
│ └─ Bootloader installation failures │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. Recovery Actions │
|
||||
│ ├─ Rollback OSTree deployment │
|
||||
│ ├─ Restore bootloader configuration │
|
||||
│ └─ Clean up partial installation │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## External Command Dependencies
|
||||
|
||||
### Required Commands
|
||||
- `ostree` - OSTree repository management
|
||||
- `bootupd` - Bootloader management
|
||||
- `podman` - Container runtime
|
||||
- `fstrim` - Filesystem optimization
|
||||
- `mount`/`umount` - Filesystem mounting
|
||||
- `fsfreeze` - Filesystem freeze/thaw
|
||||
|
||||
### Optional Commands
|
||||
- `cryptsetup` - LUKS encryption
|
||||
- `grub2-mkconfig` - GRUB configuration
|
||||
- `dracut` - Initramfs generation
|
||||
- `mkfs.*` - Filesystem creation
|
||||
|
||||
This flowchart provides a comprehensive view of the bootc installation process, showing the sequential phases, decision points, and error handling paths.
|
||||
462
install/source-code-analysis.md
Normal file
462
install/source-code-analysis.md
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
# bootc Installation Source Code Analysis
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides a detailed analysis of the bootc installation process based on the source code examination. The analysis covers the key components, data structures, and execution flow of the installation system.
|
||||
|
||||
## Core Data Structures
|
||||
|
||||
### 1. State Management
|
||||
|
||||
```rust
|
||||
// From install.rs:373-390
|
||||
pub(crate) struct State {
|
||||
pub(crate) source: SourceInfo,
|
||||
pub(crate) selinux_state: SELinuxFinalState,
|
||||
pub(crate) config_opts: InstallConfigOpts,
|
||||
pub(crate) target_imgref: ostree_container::OstreeImageReference,
|
||||
pub(crate) prepareroot_config: HashMap<String, String>,
|
||||
pub(crate) install_config: Option<config::InstallConfiguration>,
|
||||
pub(crate) root_ssh_authorized_keys: Option<String>,
|
||||
pub(crate) host_is_container: bool,
|
||||
pub(crate) container_root: Dir,
|
||||
pub(crate) tempdir: TempDir,
|
||||
}
|
||||
```
|
||||
|
||||
**Key Components**:
|
||||
- `source`: Container image information and metadata
|
||||
- `selinux_state`: SELinux configuration state
|
||||
- `target_imgref`: Target image reference for updates
|
||||
- `prepareroot_config`: OSTree prepareroot configuration
|
||||
- `install_config`: Installation-specific configuration
|
||||
|
||||
### 2. Source Information
|
||||
|
||||
```rust
|
||||
// From install.rs:360-370
|
||||
pub(crate) struct SourceInfo {
|
||||
pub(crate) imageref: ostree_container::ImageReference,
|
||||
pub(crate) digest: Option<String>,
|
||||
pub(crate) selinux: bool,
|
||||
pub(crate) in_host_mountns: bool,
|
||||
}
|
||||
```
|
||||
|
||||
**Purpose**: Encapsulates information about the source container image
|
||||
**Key Fields**:
|
||||
- `imageref`: Container image reference
|
||||
- `digest`: Image digest for verification
|
||||
- `selinux`: SELinux policy presence
|
||||
- `in_host_mountns`: Host mount namespace access
|
||||
|
||||
### 3. Root Setup
|
||||
|
||||
```rust
|
||||
// From install.rs:928-942
|
||||
pub(crate) struct RootSetup {
|
||||
#[cfg(feature = "install-to-disk")]
|
||||
luks_device: Option<String>,
|
||||
device_info: bootc_blockdev::PartitionTable,
|
||||
physical_root_path: Utf8PathBuf,
|
||||
physical_root: Dir,
|
||||
rootfs_uuid: Option<String>,
|
||||
skip_finalize: bool,
|
||||
boot: Option<MountSpec>,
|
||||
kargs: Vec<String>,
|
||||
}
|
||||
```
|
||||
|
||||
**Purpose**: Manages target filesystem setup and configuration
|
||||
**Key Fields**:
|
||||
- `device_info`: Partition table information
|
||||
- `physical_root`: Target filesystem directory
|
||||
- `rootfs_uuid`: Root filesystem UUID
|
||||
- `boot`: Boot filesystem mount specification
|
||||
- `kargs`: Kernel arguments
|
||||
|
||||
## Installation Flow Analysis
|
||||
|
||||
### 1. Preparation Phase
|
||||
|
||||
#### Container Environment Detection
|
||||
```rust
|
||||
// From install.rs:520-538
|
||||
pub(crate) fn from_container(
|
||||
root: &Dir,
|
||||
container_info: &ContainerExecutionInfo,
|
||||
) -> Result<Self> {
|
||||
if !container_info.engine.starts_with("podman") {
|
||||
anyhow::bail!("Currently this command only supports being executed via podman");
|
||||
}
|
||||
if container_info.imageid.is_empty() {
|
||||
anyhow::bail!("Invalid empty imageid");
|
||||
}
|
||||
let imageref = ostree_container::ImageReference {
|
||||
transport: ostree_container::Transport::ContainerStorage,
|
||||
name: container_info.image.clone(),
|
||||
};
|
||||
let digest = crate::podman::imageid_to_digest(&container_info.imageid)?;
|
||||
Self::new(imageref, Some(digest), root, true)
|
||||
}
|
||||
```
|
||||
|
||||
**Key Operations**:
|
||||
1. Validate podman runtime
|
||||
2. Extract image reference from container environment
|
||||
3. Resolve image digest
|
||||
4. Detect SELinux policy presence
|
||||
|
||||
#### Privilege Validation
|
||||
```rust
|
||||
// From install.rs:1061-1082
|
||||
fn require_host_pidns() -> Result<()> {
|
||||
if rustix::process::getpid().is_init() {
|
||||
anyhow::bail!("This command must be run with the podman --pid=host flag")
|
||||
}
|
||||
tracing::trace!("OK: we're not pid 1");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn require_host_userns() -> Result<()> {
|
||||
let proc1 = "/proc/1";
|
||||
let pid1_uid = Path::new(proc1)
|
||||
.metadata()
|
||||
.with_context(|| format!("Querying {proc1}"))?
|
||||
.uid();
|
||||
ensure!(pid1_uid == 0, "{proc1} is owned by {pid1_uid}, not zero; this command must be run in the root user namespace");
|
||||
tracing::trace!("OK: we're in a matching user namespace with pid1");
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
**Validation Steps**:
|
||||
1. Check process ID (not PID 1)
|
||||
2. Verify host user namespace access
|
||||
3. Validate root privileges
|
||||
|
||||
### 2. OSTree Initialization
|
||||
|
||||
#### Repository Setup
|
||||
```rust
|
||||
// From install.rs:591-694
|
||||
async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result<(Storage, bool)> {
|
||||
let sepolicy = state.load_policy()?;
|
||||
let sepolicy = sepolicy.as_ref();
|
||||
let rootfs_dir = &root_setup.physical_root;
|
||||
let cancellable = gio::Cancellable::NONE;
|
||||
let stateroot = state.stateroot();
|
||||
|
||||
let has_ostree = rootfs_dir.try_exists("ostree/repo")?;
|
||||
if !has_ostree {
|
||||
Task::new("Initializing ostree layout", "ostree")
|
||||
.args(["admin", "init-fs", "--modern", "."])
|
||||
.cwd(rootfs_dir)?
|
||||
.run()?;
|
||||
} else {
|
||||
println!("Reusing extant ostree layout");
|
||||
let path = ".".into();
|
||||
let _ = crate::utils::open_dir_remount_rw(rootfs_dir, path)
|
||||
.context("remounting target as read-write")?;
|
||||
crate::utils::remove_immutability(rootfs_dir, path)?;
|
||||
}
|
||||
// ... repository configuration
|
||||
}
|
||||
```
|
||||
|
||||
**Key Operations**:
|
||||
1. Check for existing OSTree repository
|
||||
2. Initialize repository if needed
|
||||
3. Configure repository settings
|
||||
4. Set up stateroot
|
||||
5. Configure SELinux labeling
|
||||
|
||||
#### Repository Configuration
|
||||
```rust
|
||||
// From install.rs:624-629
|
||||
for (k, v) in DEFAULT_REPO_CONFIG.iter() {
|
||||
Command::new("ostree")
|
||||
.args(["config", "--repo", "ostree/repo", "set", k, v])
|
||||
.cwd_dir(rootfs_dir.try_clone()?)
|
||||
.run_capture_stderr()?;
|
||||
}
|
||||
```
|
||||
|
||||
**Default Configuration**:
|
||||
- `sysroot.bootloader=none`
|
||||
- `sysroot.bootprefix=true`
|
||||
- `sysroot.readonly=true`
|
||||
|
||||
### 3. Container Image Deployment
|
||||
|
||||
#### Image Pulling
|
||||
```rust
|
||||
// From install.rs:755-769
|
||||
let pulled_image = match prepare_for_pull(repo, &spec_imgref, Some(&state.target_imgref))
|
||||
.await?
|
||||
{
|
||||
PreparedPullResult::AlreadyPresent(existing) => existing,
|
||||
PreparedPullResult::Ready(image_meta) => {
|
||||
check_disk_space(root_setup.physical_root.as_fd(), &image_meta, &spec_imgref)?;
|
||||
pull_from_prepared(&spec_imgref, false, ProgressWriter::default(), *image_meta).await?
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**Process**:
|
||||
1. Prepare image for pulling
|
||||
2. Check disk space requirements
|
||||
3. Pull image into OSTree repository
|
||||
4. Handle already present images
|
||||
|
||||
#### Deployment
|
||||
```rust
|
||||
// From install.rs:826-836
|
||||
let mut options = ostree_container::deploy::DeployOpts::default();
|
||||
options.kargs = Some(kargs.as_slice());
|
||||
options.target_imgref = Some(&state.target_imgref);
|
||||
options.proxy_cfg = proxy_cfg;
|
||||
options.skip_completion = true;
|
||||
options.no_clean = has_ostree;
|
||||
let imgstate = crate::utils::async_task_with_spinner(
|
||||
"Deploying container image",
|
||||
ostree_container::deploy::deploy(&sysroot, stateroot, &src_imageref, Some(options)),
|
||||
)
|
||||
.await?;
|
||||
```
|
||||
|
||||
**Deployment Options**:
|
||||
- Kernel arguments configuration
|
||||
- Target image reference
|
||||
- Proxy configuration
|
||||
- Completion skipping
|
||||
- Cleanup control
|
||||
|
||||
### 4. Bootloader Installation
|
||||
|
||||
#### Bootupd Integration
|
||||
```rust
|
||||
// From install.rs:1337-1343
|
||||
crate::bootloader::install_via_bootupd(
|
||||
&rootfs.device_info,
|
||||
&rootfs.physical_root_path,
|
||||
&state.config_opts,
|
||||
&deployment_path.as_str(),
|
||||
)?;
|
||||
```
|
||||
|
||||
**Architecture Support**:
|
||||
- x86_64/aarch64: GRUB2 via bootupd
|
||||
- s390x: zipl implementation
|
||||
- Other: Platform-specific
|
||||
|
||||
### 5. Kernel Argument Processing
|
||||
|
||||
#### Argument Collection
|
||||
```rust
|
||||
// From install.rs:773-825
|
||||
let kargsd = crate::bootc_kargs::get_kargs_from_ostree_root(
|
||||
&sysroot.repo(),
|
||||
merged_ostree_root.downcast_ref().unwrap(),
|
||||
std::env::consts::ARCH,
|
||||
)?;
|
||||
let kargsd = kargsd.iter().map(|s| s.as_str());
|
||||
|
||||
let install_config_kargs = state
|
||||
.install_config
|
||||
.as_ref()
|
||||
.and_then(|c| c.kargs.as_ref())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|s| s.as_str());
|
||||
|
||||
let kargs = root_setup
|
||||
.kargs
|
||||
.iter()
|
||||
.map(|v| v.as_str())
|
||||
.chain(install_config_kargs)
|
||||
.chain(kargsd)
|
||||
.chain(state.config_opts.karg.iter().flatten().map(|v| v.as_str()))
|
||||
.collect::<Vec<_>>();
|
||||
```
|
||||
|
||||
**Argument Sources (Priority Order)**:
|
||||
1. Root filesystem kargs
|
||||
2. Install configuration kargs
|
||||
3. Container image kargs.d files
|
||||
4. CLI-specified kargs
|
||||
|
||||
### 6. Filesystem Finalization
|
||||
|
||||
#### Optimization Process
|
||||
```rust
|
||||
// From install.rs:1033-1058
|
||||
pub(crate) fn finalize_filesystem(
|
||||
fsname: &str,
|
||||
root: &Dir,
|
||||
path: impl AsRef<Utf8Path>,
|
||||
) -> Result<()> {
|
||||
let path = path.as_ref();
|
||||
// fstrim ensures the underlying block device knows about unused space
|
||||
Task::new(format!("Trimming {fsname}"), "fstrim")
|
||||
.args(["--quiet-unsupported", "-v", path.as_str()])
|
||||
.cwd(root)?
|
||||
.run()?;
|
||||
// Remounting readonly will flush outstanding writes
|
||||
Task::new(format!("Finalizing filesystem {fsname}"), "mount")
|
||||
.cwd(root)?
|
||||
.args(["-o", "remount,ro", path.as_str()])
|
||||
.run()?;
|
||||
// Finally, freezing (and thawing) the filesystem will flush the journal
|
||||
for a in ["-f", "-u"] {
|
||||
Command::new("fsfreeze")
|
||||
.cwd_dir(root.try_clone()?)
|
||||
.args([a, path.as_str()])
|
||||
.run_capture_stderr()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
**Finalization Steps**:
|
||||
1. Trim filesystem (fstrim)
|
||||
2. Remount read-only
|
||||
3. Freeze and thaw filesystem
|
||||
4. Flush journal
|
||||
|
||||
## Error Handling Patterns
|
||||
|
||||
### 1. Contextual Error Handling
|
||||
```rust
|
||||
// From install.rs:393-404
|
||||
#[context("Loading SELinux policy")]
|
||||
pub(crate) fn load_policy(&self) -> Result<Option<ostree::SePolicy>> {
|
||||
if !self.selinux_state.enabled() {
|
||||
return Ok(None);
|
||||
}
|
||||
let r = lsm::new_sepolicy_at(&self.container_root)?
|
||||
.ok_or_else(|| anyhow::anyhow!("SELinux enabled, but no policy found in root"))?;
|
||||
tracing::debug!("Loaded SELinux policy: {}", r.csum().unwrap());
|
||||
Ok(Some(r))
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Resource Validation
|
||||
```rust
|
||||
// From install.rs:696-715
|
||||
fn check_disk_space(
|
||||
repo_fd: impl AsFd,
|
||||
image_meta: &PreparedImportMeta,
|
||||
imgref: &ImageReference,
|
||||
) -> Result<()> {
|
||||
let stat = rustix::fs::fstatvfs(repo_fd)?;
|
||||
let bytes_avail: u64 = stat.f_bsize * stat.f_bavail;
|
||||
|
||||
if image_meta.bytes_to_fetch > bytes_avail {
|
||||
anyhow::bail!(
|
||||
"Insufficient free space for {image} (available: {bytes_avail} required: {bytes_to_fetch})",
|
||||
bytes_avail = ostree_ext::glib::format_size(bytes_avail),
|
||||
bytes_to_fetch = ostree_ext::glib::format_size(image_meta.bytes_to_fetch),
|
||||
image = imgref.image,
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Graceful Degradation
|
||||
```rust
|
||||
// From install.rs:1001-1029
|
||||
pub(crate) fn reexecute_self_for_selinux_if_needed(
|
||||
srcdata: &SourceInfo,
|
||||
override_disable_selinux: bool,
|
||||
) -> Result<SELinuxFinalState> {
|
||||
if srcdata.selinux {
|
||||
let host_selinux = crate::lsm::selinux_enabled()?;
|
||||
let r = if override_disable_selinux {
|
||||
println!("notice: Target has SELinux enabled, overriding to disable");
|
||||
SELinuxFinalState::ForceTargetDisabled
|
||||
} else if host_selinux {
|
||||
setup_sys_mount("selinuxfs", SELINUXFS)?;
|
||||
let g = crate::lsm::selinux_ensure_install_or_setenforce()?;
|
||||
SELinuxFinalState::Enabled(g)
|
||||
} else {
|
||||
SELinuxFinalState::HostDisabled
|
||||
};
|
||||
Ok(r)
|
||||
} else {
|
||||
Ok(SELinuxFinalState::Disabled)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Optimizations
|
||||
|
||||
### 1. Async Operations
|
||||
```rust
|
||||
// From install.rs:1538-1543
|
||||
let rootfs = tokio::task::spawn_blocking(move || {
|
||||
baseline::install_create_rootfs(&state, block_opts)
|
||||
})
|
||||
.await??;
|
||||
```
|
||||
|
||||
### 2. Parallel Processing
|
||||
- Container image pulling
|
||||
- Filesystem operations
|
||||
- Bootloader installation
|
||||
|
||||
### 3. Resource Management
|
||||
- Temporary directory cleanup
|
||||
- File descriptor management
|
||||
- Memory usage optimization
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### 1. SELinux Integration
|
||||
- Policy detection and loading
|
||||
- Context preservation
|
||||
- Labeling operations
|
||||
|
||||
### 2. Privilege Management
|
||||
- Minimal privilege requirements
|
||||
- Capability dropping
|
||||
- Namespace isolation
|
||||
|
||||
### 3. Input Validation
|
||||
- Command argument validation
|
||||
- Path sanitization
|
||||
- Resource limit enforcement
|
||||
|
||||
## Testing and Validation
|
||||
|
||||
### 1. Unit Tests
|
||||
```rust
|
||||
// From install.rs:2064-2153
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn install_opts_serializable() {
|
||||
let c: InstallToDiskOpts = serde_json::from_value(serde_json::json!({
|
||||
"device": "/dev/vda"
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(c.block_opts.device, "/dev/vda");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Integration Tests
|
||||
- End-to-end installation testing
|
||||
- Error condition testing
|
||||
- Performance testing
|
||||
|
||||
### 3. Validation Steps
|
||||
- Container image integrity
|
||||
- Filesystem compatibility
|
||||
- Bootloader support
|
||||
- Kernel compatibility
|
||||
|
||||
This analysis provides a comprehensive understanding of the bootc installation process from a source code perspective, covering the key components, execution flow, and implementation details.
|
||||
425
install/technical-installation-guide.md
Normal file
425
install/technical-installation-guide.md
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
# bootc Technical Installation Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides a comprehensive technical explanation of how bootc installs container images as bootable operating systems. bootc bridges the gap between OCI/Docker container images and bootable host systems by providing installation mechanisms that create traditional Linux boot environments from container images.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
bootc operates in two distinct modes:
|
||||
|
||||
1. **Container Mode**: When run inside a container (during build), behaves like any other container
|
||||
2. **Host Mode**: When installed to a physical/virtual machine, becomes the bootable OS
|
||||
|
||||
The installation process transforms a container image into a bootable system with:
|
||||
- Bootloader configuration
|
||||
- Kernel and initramfs setup
|
||||
- Root filesystem deployment
|
||||
- OSTree repository initialization
|
||||
|
||||
## Installation Commands
|
||||
|
||||
### Primary Installation Commands
|
||||
|
||||
1. **`bootc install to-disk`** - Direct installation to a block device
|
||||
2. **`bootc install to-filesystem`** - Installation to an existing mounted filesystem
|
||||
3. **`bootc install to-existing-root`** - Convert existing Linux system to bootc
|
||||
4. **`bootc install finalize`** - Post-installation finalization
|
||||
|
||||
### Command Structure
|
||||
|
||||
```bash
|
||||
bootc install [COMMAND] [OPTIONS] [TARGET]
|
||||
```
|
||||
|
||||
## Technical Installation Process
|
||||
|
||||
### Phase 1: Preparation and Validation
|
||||
|
||||
#### 1.1 Container Environment Detection
|
||||
```rust
|
||||
// From install.rs:519-538
|
||||
pub(crate) fn from_container(
|
||||
root: &Dir,
|
||||
container_info: &ContainerExecutionInfo,
|
||||
) -> Result<Self> {
|
||||
if !container_info.engine.starts_with("podman") {
|
||||
anyhow::bail!("Currently this command only supports being executed via podman");
|
||||
}
|
||||
// ... validation logic
|
||||
}
|
||||
```
|
||||
|
||||
**External Commands Required:**
|
||||
- `podman` - Container runtime (required)
|
||||
- `ostree` - OSTree repository management
|
||||
- `bootupd` - Bootloader management
|
||||
|
||||
#### 1.2 Privilege and Namespace Validation
|
||||
```rust
|
||||
// From install.rs:1061-1082
|
||||
fn require_host_pidns() -> Result<()> {
|
||||
if rustix::process::getpid().is_init() {
|
||||
anyhow::bail!("This command must be run with the podman --pid=host flag")
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
**Required Container Flags:**
|
||||
- `--privileged` - Full host access
|
||||
- `--pid=host` - Host process namespace
|
||||
- `--security-opt label=type:unconfined_t` - SELinux bypass
|
||||
|
||||
#### 1.3 SELinux State Management
|
||||
```rust
|
||||
// From install.rs:1001-1029
|
||||
pub(crate) fn reexecute_self_for_selinux_if_needed(
|
||||
srcdata: &SourceInfo,
|
||||
override_disable_selinux: bool,
|
||||
) -> Result<SELinuxFinalState> {
|
||||
// SELinux policy detection and re-execution logic
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 2: Filesystem Setup
|
||||
|
||||
#### 2.1 OSTree Repository Initialization
|
||||
```rust
|
||||
// From install.rs:591-694
|
||||
async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result<(Storage, bool)> {
|
||||
let has_ostree = rootfs_dir.try_exists("ostree/repo")?;
|
||||
if !has_ostree {
|
||||
Task::new("Initializing ostree layout", "ostree")
|
||||
.args(["admin", "init-fs", "--modern", "."])
|
||||
.cwd(rootfs_dir)?
|
||||
.run()?;
|
||||
}
|
||||
// ... repository configuration
|
||||
}
|
||||
```
|
||||
|
||||
**External Commands:**
|
||||
- `ostree admin init-fs --modern` - Initialize OSTree filesystem
|
||||
- `ostree config set` - Configure repository settings
|
||||
|
||||
#### 2.2 Container Image Deployment
|
||||
```rust
|
||||
// From install.rs:718-892
|
||||
async fn install_container(
|
||||
state: &State,
|
||||
root_setup: &RootSetup,
|
||||
sysroot: &ostree::Sysroot,
|
||||
has_ostree: bool,
|
||||
) -> Result<(ostree::Deployment, InstallAleph)> {
|
||||
// Pull container image into OSTree repository
|
||||
let pulled_image = match prepare_for_pull(repo, &spec_imgref, Some(&state.target_imgref)).await? {
|
||||
PreparedPullResult::AlreadyPresent(existing) => existing,
|
||||
PreparedPullResult::Ready(image_meta) => {
|
||||
check_disk_space(root_setup.physical_root.as_fd(), &image_meta, &spec_imgref)?;
|
||||
pull_from_prepared(&spec_imgref, false, ProgressWriter::default(), *image_meta).await?
|
||||
}
|
||||
};
|
||||
// ... deployment logic
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: Bootloader Installation
|
||||
|
||||
#### 3.1 Bootupd Integration
|
||||
```rust
|
||||
// From install.rs:1337-1343
|
||||
crate::bootloader::install_via_bootupd(
|
||||
&rootfs.device_info,
|
||||
&rootfs.physical_root_path,
|
||||
&state.config_opts,
|
||||
&deployment_path.as_str(),
|
||||
)?;
|
||||
```
|
||||
|
||||
**External Commands:**
|
||||
- `bootupctl install` - Install bootloader
|
||||
- `bootupctl generate` - Generate bootloader configuration
|
||||
|
||||
#### 3.2 Architecture-Specific Bootloaders
|
||||
- **x86_64/aarch64**: GRUB2 via bootupd
|
||||
- **s390x**: zipl (IBM Z)
|
||||
- **Other**: Platform-specific implementations
|
||||
|
||||
### Phase 4: Kernel and Initramfs Setup
|
||||
|
||||
#### 4.1 Kernel Argument Processing
|
||||
```rust
|
||||
// From install.rs:773-825
|
||||
let kargsd = crate::bootc_kargs::get_kargs_from_ostree_root(
|
||||
&sysroot.repo(),
|
||||
merged_ostree_root.downcast_ref().unwrap(),
|
||||
std::env::consts::ARCH,
|
||||
)?;
|
||||
```
|
||||
|
||||
**Kernel Arguments Sources (in order):**
|
||||
1. Root filesystem kargs
|
||||
2. Install configuration kargs
|
||||
3. Container image kargs.d files
|
||||
4. CLI-specified kargs
|
||||
|
||||
#### 4.2 Initramfs Integration
|
||||
- Kernel location: `/usr/lib/modules/$kver/vmlinuz`
|
||||
- Initramfs location: `/usr/lib/modules/$kver/initramfs.img`
|
||||
- Generated by dracut during container build
|
||||
|
||||
### Phase 5: Filesystem Finalization
|
||||
|
||||
#### 5.1 Filesystem Optimization
|
||||
```rust
|
||||
// From install.rs:1033-1058
|
||||
pub(crate) fn finalize_filesystem(
|
||||
fsname: &str,
|
||||
root: &Dir,
|
||||
path: impl AsRef<Utf8Path>,
|
||||
) -> Result<()> {
|
||||
// fstrim - optimize filesystem
|
||||
Task::new(format!("Trimming {fsname}"), "fstrim")
|
||||
.args(["--quiet-unsupported", "-v", path.as_str()])
|
||||
.cwd(root)?
|
||||
.run()?;
|
||||
|
||||
// Remount read-only
|
||||
Task::new(format!("Finalizing filesystem {fsname}"), "mount")
|
||||
.cwd(root)?
|
||||
.args(["-o", "remount,ro", path.as_str()])
|
||||
.run()?;
|
||||
|
||||
// Freeze/thaw for journal flush
|
||||
for a in ["-f", "-u"] {
|
||||
Command::new("fsfreeze")
|
||||
.cwd_dir(root.try_clone()?)
|
||||
.args([a, path.as_str()])
|
||||
.run_capture_stderr()?;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**External Commands:**
|
||||
- `fstrim` - Trim filesystem for optimization
|
||||
- `mount -o remount,ro` - Remount read-only
|
||||
- `fsfreeze` - Freeze/thaw for journal flush
|
||||
|
||||
## Installation Modes
|
||||
|
||||
### 1. to-disk Installation
|
||||
|
||||
**Process Flow:**
|
||||
1. Create filesystem on target device
|
||||
2. Mount target device
|
||||
3. Deploy container image to mounted filesystem
|
||||
4. Install bootloader
|
||||
5. Unmount and finalize
|
||||
|
||||
**External Commands:**
|
||||
```bash
|
||||
mkfs.$filesystem_type /dev/target
|
||||
mount /dev/target /mnt
|
||||
bootc install to-filesystem --karg=root=UUID=<uuid> /mnt
|
||||
umount /mnt
|
||||
```
|
||||
|
||||
### 2. to-filesystem Installation
|
||||
|
||||
**Process Flow:**
|
||||
1. Validate target filesystem
|
||||
2. Initialize OSTree repository
|
||||
3. Deploy container image
|
||||
4. Configure bootloader
|
||||
5. Finalize filesystem
|
||||
|
||||
**Use Cases:**
|
||||
- Integration with external installers (Anaconda)
|
||||
- Custom partitioning schemes
|
||||
- Cloud image generation
|
||||
|
||||
### 3. to-existing-root Installation
|
||||
|
||||
**Process Flow:**
|
||||
1. Mount host root filesystem
|
||||
2. Clean boot directories
|
||||
3. Deploy alongside existing system
|
||||
4. Configure bootloader
|
||||
5. Set up cleanup service
|
||||
|
||||
**Special Considerations:**
|
||||
- Preserves existing data in `/sysroot`
|
||||
- Requires `--acknowledge-destructive` flag
|
||||
- Sets up cleanup service for first boot
|
||||
|
||||
## External Dependencies
|
||||
|
||||
### Required System Commands
|
||||
|
||||
| Command | Purpose | Package |
|
||||
|---------|---------|---------|
|
||||
| `ostree` | OSTree repository management | ostree |
|
||||
| `bootupd` | Bootloader management | bootupd |
|
||||
| `podman` | Container runtime | podman |
|
||||
| `fstrim` | Filesystem optimization | util-linux |
|
||||
| `mount` | Filesystem mounting | util-linux |
|
||||
| `umount` | Filesystem unmounting | util-linux |
|
||||
| `fsfreeze` | Filesystem freeze/thaw | util-linux |
|
||||
|
||||
### Optional Commands
|
||||
|
||||
| Command | Purpose | Package |
|
||||
|---------|---------|---------|
|
||||
| `cryptsetup` | LUKS encryption | cryptsetup |
|
||||
| `grub2-mkconfig` | GRUB configuration | grub2-tools |
|
||||
| `dracut` | Initramfs generation | dracut |
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### 1. Install Configuration
|
||||
Location: `/usr/lib/bootc/install/*.toml`
|
||||
|
||||
```toml
|
||||
[install.filesystem.root]
|
||||
type = "xfs"
|
||||
|
||||
[install.filesystem.boot]
|
||||
type = "ext4"
|
||||
```
|
||||
|
||||
### 2. Kernel Arguments
|
||||
Location: `/usr/lib/bootc/kargs.d/*.toml`
|
||||
|
||||
```toml
|
||||
[kargs]
|
||||
append = ["console=ttyS0", "quiet"]
|
||||
prepend = ["rd.luks.uuid=12345678-1234-1234-1234-123456789abc"]
|
||||
```
|
||||
|
||||
### 3. OSTree Configuration
|
||||
Location: `ostree/repo/config`
|
||||
|
||||
```ini
|
||||
[core]
|
||||
repo_version=1
|
||||
mode=bare
|
||||
|
||||
[sysroot]
|
||||
bootloader=none
|
||||
bootprefix=true
|
||||
readonly=true
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### 1. SELinux Integration
|
||||
- Automatic policy detection
|
||||
- Re-execution for proper labeling
|
||||
- Target system SELinux configuration
|
||||
|
||||
### 2. Container Security
|
||||
- Requires privileged container execution
|
||||
- Host mount namespace access
|
||||
- Device access for installation
|
||||
|
||||
### 3. Filesystem Security
|
||||
- Atomic operations where possible
|
||||
- Proper file permissions
|
||||
- SELinux labeling
|
||||
|
||||
## Error Handling and Recovery
|
||||
|
||||
### 1. Disk Space Validation
|
||||
```rust
|
||||
// From install.rs:696-715
|
||||
fn check_disk_space(
|
||||
repo_fd: impl AsFd,
|
||||
image_meta: &PreparedImportMeta,
|
||||
imgref: &ImageReference,
|
||||
) -> Result<()> {
|
||||
let stat = rustix::fs::fstatvfs(repo_fd)?;
|
||||
let bytes_avail: u64 = stat.f_bsize * stat.f_bavail;
|
||||
|
||||
if image_meta.bytes_to_fetch > bytes_avail {
|
||||
anyhow::bail!(
|
||||
"Insufficient free space for {image} (available: {bytes_avail} required: {bytes_to_fetch})",
|
||||
// ... error details
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Rollback Capability
|
||||
- OSTree provides atomic rollback
|
||||
- Bootloader configuration backup
|
||||
- Deployment state tracking
|
||||
|
||||
### 3. Validation Steps
|
||||
- Container image integrity
|
||||
- Filesystem compatibility
|
||||
- Bootloader support
|
||||
- Kernel compatibility
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### 1. Parallel Operations
|
||||
- Container image pulling
|
||||
- Filesystem operations
|
||||
- Bootloader installation
|
||||
|
||||
### 2. Disk I/O Optimization
|
||||
- OSTree repository configuration
|
||||
- Filesystem trimming
|
||||
- Write optimization
|
||||
|
||||
### 3. Memory Usage
|
||||
- Container image caching
|
||||
- OSTree repository management
|
||||
- Temporary file handling
|
||||
|
||||
## Debugging and Troubleshooting
|
||||
|
||||
### 1. Logging
|
||||
- Structured logging with tracing
|
||||
- Journal integration
|
||||
- Progress reporting
|
||||
|
||||
### 2. Common Issues
|
||||
- Insufficient disk space
|
||||
- SELinux policy conflicts
|
||||
- Bootloader installation failures
|
||||
- Container image access issues
|
||||
|
||||
### 3. Debug Commands
|
||||
```bash
|
||||
# Check OSTree repository
|
||||
ostree admin status
|
||||
|
||||
# Verify bootloader
|
||||
bootupctl status
|
||||
|
||||
# Check container image
|
||||
podman images
|
||||
|
||||
# Validate filesystem
|
||||
lsblk -f
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### 1. Planned Features
|
||||
- Dynamic ConfigMap injection
|
||||
- Enhanced rollback mechanisms
|
||||
- Multi-architecture support
|
||||
- Cloud integration improvements
|
||||
|
||||
### 2. API Evolution
|
||||
- Stable CLI interface
|
||||
- REST API for management
|
||||
- Configuration management
|
||||
- Monitoring integration
|
||||
|
||||
---
|
||||
|
||||
This technical guide provides the foundation for understanding bootc's installation process. The system is designed to be robust, secure, and maintainable while providing the flexibility needed for various deployment scenarios.
|
||||
Loading…
Add table
Add a link
Reference in a new issue