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
419
composefs.md
Normal file
419
composefs.md
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
# bootc Composefs Integration - Technical Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
This document explains how bootc utilizes Composefs as an alternative storage backend to OSTree. The composefs-backend branch introduces direct container image deployment without OSTree conversion.
|
||||
|
||||
## What is Composefs?
|
||||
|
||||
Composefs is a Linux kernel filesystem that mounts read-only EROFS images directly from userspace:
|
||||
|
||||
- **Direct Container Support**: Mount OCI images without conversion
|
||||
- **Kernel Performance**: No userspace daemon required
|
||||
- **Built-in Security**: fsverity integration for integrity verification
|
||||
- **Storage Efficiency**: EROFS compression and deduplication
|
||||
|
||||
## Why Composefs is Needed
|
||||
|
||||
### Main Branch (OSTree) Problems
|
||||
|
||||
1. **Container Conversion**: OCI images must be converted to OSTree format
|
||||
2. **Performance Overhead**: Userspace operations for file access
|
||||
3. **Storage Inefficiency**: OSTree object model creates overhead
|
||||
4. **Complex Deployment**: Multi-step conversion process
|
||||
|
||||
### Composefs-Backend Solutions
|
||||
|
||||
1. **Direct Container Support**: No conversion needed
|
||||
2. **Kernel Performance**: Direct kernel mounting
|
||||
3. **Storage Efficiency**: EROFS compression and layer deduplication
|
||||
4. **Simplified Architecture**: Fewer moving parts
|
||||
|
||||
## Architecture Comparison
|
||||
|
||||
### Main Branch (OSTree Backend)
|
||||
```
|
||||
Container Image → OSTree Conversion → OSTree Repository → Deployment
|
||||
```
|
||||
|
||||
**Components:**
|
||||
- OSTree repository with converted images
|
||||
- Deployment objects for state management
|
||||
- Userspace file access through OSTree library
|
||||
- OCI to OSTree conversion layer
|
||||
|
||||
### Composefs-Backend Branch
|
||||
```
|
||||
Container Image → EROFS Image → Composefs Mount → Direct Access
|
||||
```
|
||||
|
||||
**Components:**
|
||||
- Composefs repository with EROFS images
|
||||
- Direct kernel mounting via composefs
|
||||
- Native container image support
|
||||
- No conversion required
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### 1. Repository Structure
|
||||
|
||||
**Main Branch:**
|
||||
```
|
||||
/sysroot/ostree/
|
||||
├── repo/objects/ # OSTree objects
|
||||
├── repo/refs/ # References
|
||||
└── deploy/{id}/ # Deployment checkout
|
||||
├── usr/ # System files
|
||||
├── etc/ # Configuration
|
||||
└── var/ # Variable data
|
||||
```
|
||||
|
||||
**Composefs-Backend:**
|
||||
```
|
||||
/sysroot/
|
||||
├── composefs/ # EROFS images
|
||||
├── state/deploy/{id}/ # Deployment states
|
||||
│ ├── etc/ # Merged /etc
|
||||
│ ├── var -> # Symlink to shared /var
|
||||
│ └── {id}.origin # Metadata
|
||||
└── boot/ # Bootloader config
|
||||
├── loader/ # BLS entries
|
||||
└── grub2/ # GRUB config
|
||||
```
|
||||
|
||||
### 2. Image Storage
|
||||
|
||||
**Main Branch (OSTree):**
|
||||
```rust
|
||||
// Must convert OCI to OSTree
|
||||
let ostree_ref = ostree_container::OstreeImageReference {
|
||||
sigverify: SignatureSource::ContainerPolicy,
|
||||
imgref: ImageReference {
|
||||
transport: Transport::Registry,
|
||||
name: "quay.io/myorg/debian-bootc:v2.0".to_string(),
|
||||
},
|
||||
};
|
||||
|
||||
let deployment = ostree_container::deploy::deploy(&sysroot, &ostree_ref, &deploy_opts)?;
|
||||
```
|
||||
|
||||
**Composefs-Backend:**
|
||||
```rust
|
||||
// Direct OCI image pull
|
||||
pub(crate) async fn pull_composefs_repo(transport: &String, image: &String) -> Result<(...)> {
|
||||
let repo = open_composefs_repo(&rootfs_dir)?;
|
||||
|
||||
// Pull directly from registry
|
||||
let (id, verity) = composefs_oci_pull(
|
||||
&Arc::new(repo),
|
||||
&format!("{transport}:{image}"),
|
||||
None,
|
||||
None
|
||||
).await?;
|
||||
|
||||
// Create EROFS filesystem
|
||||
let mut fs = create_composefs_filesystem(&repo, &hex::encode(id), None)?;
|
||||
let entries = fs.transform_for_boot(&repo)?;
|
||||
let id = fs.commit_image(&repo, None)?;
|
||||
|
||||
Ok((repo, entries, id, fs))
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Boot Configuration
|
||||
|
||||
**Main Branch (BLS only):**
|
||||
```rust
|
||||
let bls_config = BLSConfig {
|
||||
title: "bootc".to_string(),
|
||||
options: Some("root=ostree:ostree=1:deploy-id={id}".to_string()),
|
||||
};
|
||||
```
|
||||
|
||||
**Composefs-Backend (BLS + UKI):**
|
||||
```rust
|
||||
#[derive(ValueEnum, Debug, Copy, Clone)]
|
||||
pub enum BootType {
|
||||
Bls, // Boot Loader Specification
|
||||
Uki, // Unified Kernel Image
|
||||
}
|
||||
|
||||
let bls_config = BLSConfig {
|
||||
title: "bootc-composefs".to_string(),
|
||||
options: Some("composefs=sha256:{digest}".to_string()),
|
||||
};
|
||||
```
|
||||
|
||||
### 4. Kernel Integration
|
||||
|
||||
**Main Branch:**
|
||||
```rust
|
||||
// Uses root= parameter
|
||||
let root_param = format!("root=ostree:ostree=1:deploy-id={deployment_id}");
|
||||
```
|
||||
|
||||
**Composefs-Backend:**
|
||||
```rust
|
||||
// Uses composefs= parameter
|
||||
pub const COMPOSEFS_CMDLINE: &str = "composefs";
|
||||
|
||||
pub(crate) struct ComposefsCmdline {
|
||||
pub insecure: bool,
|
||||
pub digest: Box<str>,
|
||||
}
|
||||
|
||||
// Kernel parameter: composefs=sha256:abc123... or composefs=?sha256:abc123... (insecure)
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
### Main Branch (OSTree)
|
||||
```rust
|
||||
// OSTree deployment objects
|
||||
let deployments = sysroot.deployments();
|
||||
let booted_deployment = sysroot.booted_deployment();
|
||||
```
|
||||
|
||||
### Composefs-Backend
|
||||
```rust
|
||||
// Custom state management
|
||||
pub(crate) fn write_composefs_state(
|
||||
root_path: &Utf8PathBuf,
|
||||
deployment_id: Sha256HashValue,
|
||||
imgref: &ImageReference,
|
||||
staged: bool,
|
||||
boot_type: BootType,
|
||||
boot_digest: Option<String>,
|
||||
) -> Result<()> {
|
||||
let state_path = root_path.join(format!("{STATE_DIR_RELATIVE}/{}", deployment_id.to_hex()));
|
||||
|
||||
// Create deployment directory
|
||||
create_dir_all(state_path.join("etc"))?;
|
||||
|
||||
// Copy pristine /etc from EROFS image
|
||||
copy_etc_to_state(&root_path, &deployment_id.to_hex(), &state_path)?;
|
||||
|
||||
// Create symlink to shared /var
|
||||
let actual_var_path = root_path.join(SHARED_VAR_PATH);
|
||||
create_dir_all(&actual_var_path)?;
|
||||
|
||||
symlink(
|
||||
path_relative_to(state_path.as_std_path(), actual_var_path.as_std_path())?,
|
||||
state_path.join("var"),
|
||||
)?;
|
||||
|
||||
// Write deployment metadata
|
||||
let mut config = tini::Ini::new()
|
||||
.section("origin")
|
||||
.item(ORIGIN_CONTAINER, format!("ostree-unverified-image:{transport}{image_name}"));
|
||||
|
||||
config = config
|
||||
.section(ORIGIN_KEY_BOOT)
|
||||
.item(ORIGIN_KEY_BOOT_TYPE, boot_type);
|
||||
|
||||
if let Some(boot_digest) = boot_digest {
|
||||
config = config
|
||||
.section(ORIGIN_KEY_BOOT)
|
||||
.item(ORIGIN_KEY_BOOT_DIGEST, boot_digest);
|
||||
}
|
||||
|
||||
// Write .origin file
|
||||
state_dir.atomic_write(
|
||||
format!("{}.origin", deployment_id.to_hex()),
|
||||
config.to_string().as_bytes(),
|
||||
)?;
|
||||
|
||||
// Handle staged deployments
|
||||
if staged {
|
||||
std::fs::create_dir_all(COMPOSEFS_TRANSIENT_STATE_DIR)?;
|
||||
let staged_depl_dir = cap_std::fs::Dir::open_ambient_dir(
|
||||
COMPOSEFS_TRANSIENT_STATE_DIR,
|
||||
cap_std::ambient_authority(),
|
||||
)?;
|
||||
|
||||
staged_depl_dir.atomic_write(
|
||||
COMPOSEFS_STAGED_DEPLOYMENT_FNAME,
|
||||
deployment_id.to_hex().as_bytes(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## /etc Management
|
||||
|
||||
### Main Branch (OSTree)
|
||||
```rust
|
||||
// OSTree 3-way merge
|
||||
let pristine_etc = sysroot.deployment_get_origin_file(booted_deployment, "etc")?;
|
||||
let current_etc = Dir::open_ambient_dir("/etc", ambient_authority())?;
|
||||
let new_etc = sysroot.deployment_get_origin_file(staged_deployment, "etc")?;
|
||||
let merged_etc = ostree_merge_etc(&pristine_etc, ¤t_etc, &new_etc)?;
|
||||
```
|
||||
|
||||
### Composefs-Backend
|
||||
```rust
|
||||
// Composefs 3-way merge with EROFS
|
||||
pub(crate) async fn composefs_native_finalize() -> Result<()> {
|
||||
// Mount EROFS image for pristine /etc
|
||||
let sysroot = open_dir(CWD, "/sysroot")?;
|
||||
let composefs_fd = mount_composefs_image(&sysroot, &booted_composefs.verity, false)?;
|
||||
let erofs_tmp_mnt = TempMount::mount_fd(&composefs_fd)?;
|
||||
|
||||
// Perform 3-way merge
|
||||
let pristine_etc = Dir::open_ambient_dir(
|
||||
erofs_tmp_mnt.dir.path().join("etc"),
|
||||
ambient_authority()
|
||||
)?;
|
||||
let current_etc = Dir::open_ambient_dir("/etc", ambient_authority())?;
|
||||
|
||||
let new_etc_path = Path::new(STATE_DIR_ABS)
|
||||
.join(&staged_composefs.verity)
|
||||
.join("etc");
|
||||
let new_etc = Dir::open_ambient_dir(new_etc_path, ambient_authority())?;
|
||||
|
||||
let (pristine_files, current_files, new_files) =
|
||||
traverse_etc(&pristine_etc, ¤t_etc, &new_etc)?;
|
||||
|
||||
let diff = compute_diff(&pristine_files, ¤t_files)?;
|
||||
merge(¤t_etc, ¤t_files, &new_etc, &new_files, diff)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Boot Process
|
||||
|
||||
### Main Branch (OSTree)
|
||||
1. **Kernel Boot**: `root=ostree:ostree=1:deploy-id={id}`
|
||||
2. **OSTree Mount**: Mount OSTree repository
|
||||
3. **Deployment Checkout**: Checkout deployment files
|
||||
4. **Userspace Access**: Access files through OSTree library
|
||||
|
||||
### Composefs-Backend
|
||||
1. **Kernel Boot**: `composefs=sha256:{digest}`
|
||||
2. **EROFS Mount**: Kernel directly mounts EROFS image
|
||||
3. **Direct Access**: No userspace daemon required
|
||||
4. **Verity Verification**: Built-in integrity checking
|
||||
|
||||
## CLI Integration
|
||||
|
||||
### Main Branch
|
||||
```rust
|
||||
// Direct OSTree operations
|
||||
match opt {
|
||||
Opt::Upgrade(opts) => upgrade(opts).await,
|
||||
Opt::Switch(opts) => switch(opts).await,
|
||||
Opt::Rollback(opts) => rollback(opts).await,
|
||||
}
|
||||
```
|
||||
|
||||
### Composefs-Backend
|
||||
```rust
|
||||
// Conditional backend selection
|
||||
match opt {
|
||||
Opt::Upgrade(opts) => {
|
||||
#[cfg(feature = "composefs-backend")]
|
||||
if composefs_booted()?.is_some() {
|
||||
upgrade_composefs(opts).await
|
||||
} else {
|
||||
upgrade(opts).await
|
||||
}
|
||||
}
|
||||
Opt::Switch(opts) => {
|
||||
#[cfg(feature = "composefs-backend")]
|
||||
if composefs_booted()?.is_some() {
|
||||
switch_composefs(opts).await
|
||||
} else {
|
||||
switch(opts).await
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Systemd Integration
|
||||
|
||||
### Main Branch
|
||||
Uses standard OSTree systemd services.
|
||||
|
||||
### Composefs-Backend
|
||||
New systemd service for composefs finalization:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Composefs Finalize Staged Deployment
|
||||
Documentation=man:bootc(1)
|
||||
DefaultDependencies=no
|
||||
|
||||
RequiresMountsFor=/sysroot
|
||||
After=local-fs.target
|
||||
Before=basic.target final.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStop=/usr/bin/bootc composefs-finalize-staged
|
||||
TimeoutStopSec=5m
|
||||
ProtectHome=yes
|
||||
ReadOnlyPaths=/etc
|
||||
```
|
||||
|
||||
## Key Differences
|
||||
|
||||
| Aspect | Main Branch (OSTree) | Composefs-Backend |
|
||||
|--------|---------------------|-------------------|
|
||||
| **Storage** | OSTree repository | EROFS images |
|
||||
| **Container Support** | Conversion required | Direct OCI support |
|
||||
| **Boot Methods** | BLS only | BLS + UKI |
|
||||
| **Kernel Integration** | Limited | Native composefs |
|
||||
| **Performance** | Userspace overhead | Kernel-native |
|
||||
| **Security** | External fsverity | Built-in fsverity |
|
||||
| **Boot Process** | `root=ostree:...` | `composefs=sha256:...` |
|
||||
|
||||
## External Commands
|
||||
|
||||
### Composefs Operations
|
||||
```bash
|
||||
# Mount EROFS image
|
||||
mount -t erofs /dev/loop0 /mnt
|
||||
|
||||
# Create EROFS image
|
||||
mkfs.erofs -o image.erofs /source/directory
|
||||
|
||||
# Mount composefs
|
||||
mount -t composefs /dev/loop0 /mnt
|
||||
|
||||
# Create composefs image
|
||||
composefs-util create /source /destination
|
||||
```
|
||||
|
||||
### Container Registry
|
||||
```bash
|
||||
# Pull container image
|
||||
podman pull quay.io/myorg/debian-bootc:v2.0
|
||||
|
||||
# Inspect image
|
||||
podman inspect quay.io/myorg/debian-bootc:v2.0
|
||||
```
|
||||
|
||||
### Bootloader Configuration
|
||||
```bash
|
||||
# Update GRUB
|
||||
grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
|
||||
# Update systemd-boot
|
||||
bootctl update
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
The composefs-backend branch provides significant improvements over the main branch:
|
||||
|
||||
1. **Better Performance**: Kernel-native mounting eliminates userspace overhead
|
||||
2. **Direct Container Support**: No conversion needed for OCI images
|
||||
3. **Enhanced Security**: Built-in fsverity verification
|
||||
4. **Storage Efficiency**: Better compression and deduplication
|
||||
5. **Simplified Architecture**: Fewer moving parts, more reliable
|
||||
|
||||
The conditional compilation approach allows gradual adoption while maintaining backward compatibility with the OSTree backend.
|
||||
Loading…
Add table
Add a link
Reference in a new issue