- 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
11 KiB
bootc upgrade - Technical Reference
Architecture Overview
The bootc upgrade system is built on OSTree's A/B deployment model, providing transactional updates with rollback capabilities. The system integrates with container registries to pull updates and stages them for application at the next boot.
Core Components
1. Upgrade Command Structure
// From cli.rs:64-89
pub(crate) struct UpgradeOpts {
pub(crate) quiet: bool, // Suppress progress output
pub(crate) check: bool, // Check-only mode
pub(crate) apply: bool, // Apply and reboot
pub(crate) soft_reboot: Option<SoftRebootMode>, // Soft reboot behavior
pub(crate) progress: ProgressOptions, // Progress reporting
}
Purpose: Command-line interface configuration Features: Mutually exclusive options, progress control, soft reboot support
2. Upgrade Implementation
// From cli.rs:860-969
async fn upgrade(opts: UpgradeOpts) -> Result<()> {
let sysroot = &get_storage().await?;
let ostree = sysroot.get_ostree()?;
let repo = &ostree.repo();
let (booted_deployment, _deployments, host) = crate::status::get_status_require_booted(ostree)?;
let imgref = host.spec.image.as_ref();
let prog: ProgressWriter = opts.progress.try_into()?;
// ... upgrade logic
}
Process Flow:
- System Validation: Check system status and compatibility
- Image Resolution: Determine source image reference
- Update Check: Verify if updates are available
- Download/Stage: Pull and stage updates
- Application: Apply updates if requested
Upgrade Modes
1. Check Mode (--check)
// From cli.rs:894-915
if opts.check {
let imgref = imgref.clone().into();
let mut imp = crate::deploy::new_importer(repo, &imgref).await?;
match imp.prepare().await? {
PrepareResult::AlreadyPresent(_) => {
println!("No changes in: {imgref:#}");
}
PrepareResult::Ready(r) => {
crate::deploy::check_bootc_label(&r.config);
println!("Update available for: {imgref:#}");
if let Some(version) = r.version() {
println!(" Version: {version}");
}
println!(" Digest: {}", r.manifest_digest);
changed = true;
// ... diff printing
}
}
}
Purpose: Check for updates without downloading Benefits: Fast execution, minimal bandwidth usage Output: Update availability, version info, digest comparison
2. Download Mode (default)
// From cli.rs:916-949
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
let staged_digest = staged_image.map(|s| s.digest().expect("valid digest in status"));
let fetched_digest = &fetched.manifest_digest;
let staged_unchanged = staged_digest
.as_ref()
.map(|d| d == fetched_digest)
.unwrap_or_default();
let booted_unchanged = booted_image
.as_ref()
.map(|img| &img.manifest_digest == fetched_digest)
.unwrap_or_default();
if staged_unchanged {
println!("Staged update present, not changed.");
handle_staged_soft_reboot(ostree, opts.soft_reboot, &host)?;
if opts.apply {
crate::reboot::reboot()?;
}
} else if booted_unchanged {
println!("No update available.")
} else {
let osname = booted_deployment.osname();
crate::deploy::stage(sysroot, &osname, &fetched, &spec, prog.clone()).await?;
changed = true;
// ... diff printing
}
Purpose: Download and stage updates Process: Registry pull → OSTree import → Staging → Status update Features: Duplicate detection, progress reporting, diff display
3. Apply Mode (--apply)
// From cli.rs:951-968
if changed {
sysroot.update_mtime()?;
if opts.soft_reboot.is_some() {
let updated_host = crate::status::get_status(ostree, Some(&booted_deployment))?.1;
handle_staged_soft_reboot(ostree, opts.soft_reboot, &updated_host)?;
}
if opts.apply {
crate::reboot::reboot()?;
}
} else {
tracing::debug!("No changes");
}
Purpose: Apply staged updates and reboot Process: Update system status → Handle soft reboot → Reboot system Features: Soft reboot support, automatic reboot, status updates
Soft Reboot System
1. Soft Reboot Modes
// From cli.rs:81-85
#[clap(long = "soft-reboot", conflicts_with = "check")]
pub(crate) soft_reboot: Option<SoftRebootMode>,
Modes:
required: Fail if soft reboot unavailableauto: Use soft reboot if available, fallback to regular reboot
2. Soft Reboot Handling
// From cli.rs:954-959
if opts.soft_reboot.is_some() {
let updated_host = crate::status::get_status(ostree, Some(&booted_deployment))?.1;
handle_staged_soft_reboot(ostree, opts.soft_reboot, &updated_host)?;
}
Purpose: Configure soft reboot behavior Process: Check availability → Configure if supported → Fallback if needed
Registry Integration
1. Image Reference Resolution
// From cli.rs:865-889
let imgref = host.spec.image.as_ref();
let booted_image = host
.status
.booted
.as_ref()
.map(|b| b.query_image(repo))
.transpose()?
.flatten();
let imgref = imgref.ok_or_else(|| anyhow::anyhow!("No image source specified"))?;
Purpose: Determine source image for updates Process: Get from host spec → Validate availability → Use for upgrade
2. Container Registry Pull
// From cli.rs:917
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
Purpose: Download container image from registry Process: Registry authentication → Layer download → OSTree conversion Features: Progress reporting, error handling, signature verification
OSTree Integration
1. Deployment Management
// From cli.rs:864
let (booted_deployment, _deployments, host) = crate::status::get_status_require_booted(ostree)?;
Purpose: Get current system state Process: Query OSTree → Get booted deployment → Get host configuration
2. Staging Process
// From cli.rs:940
crate::deploy::stage(sysroot, &osname, &fetched, &spec, prog.clone()).await?;
Purpose: Stage updates for next boot Process: Create new deployment → Configure bootloader → Update status Features: Atomic staging, rollback capability, state preservation
Status Management
1. System Status Query
// From cli.rs:864
let (booted_deployment, _deployments, host) = crate::status::get_status_require_booted(ostree)?;
Purpose: Get current system state Returns: Booted deployment, all deployments, host configuration
2. Status Updates
// From cli.rs:952
sysroot.update_mtime()?;
Purpose: Update system modification time Process: Update filesystem timestamp → Trigger status refresh
Error Handling
1. Compatibility Checks
// From cli.rs:869-879
if imgref.is_none() {
let booted_incompatible = host.status.booted.as_ref().is_some_and(|b| b.incompatible);
let staged_incompatible = host.status.staged.as_ref().is_some_and(|b| b.incompatible);
if booted_incompatible || staged_incompatible {
return Err(anyhow::anyhow!(
"Deployment contains local rpm-ostree modifications; cannot upgrade via bootc. You can run `rpm-ostree reset` to undo the modifications."
));
}
}
Purpose: Check system compatibility Checks: Local modifications, incompatible deployments Error: Prevents upgrade on incompatible systems
2. Update Validation
// From cli.rs:902
crate::deploy::check_bootc_label(&r.config);
Purpose: Validate container image compatibility Checks: bootc labels, image configuration Error: Prevents upgrade of incompatible images
Progress Reporting
1. Progress Writer
// From cli.rs:866
let prog: ProgressWriter = opts.progress.try_into()?;
Purpose: Handle progress output Features: Quiet mode support, progress bars, status updates
2. Progress Options
// From cli.rs:87-88
#[clap(flatten)]
pub(crate) progress: ProgressOptions,
Purpose: Configure progress display Options: Quiet mode, progress bars, status updates
Diff and Comparison
1. Manifest Comparison
// From cli.rs:910-913
if let Some(previous_image) = booted_image.as_ref() {
let diff = ostree_container::ManifestDiff::new(&previous_image.manifest, &r.manifest);
diff.print();
}
Purpose: Show differences between images Process: Compare manifests → Generate diff → Display changes Features: Layer changes, configuration differences, size changes
2. Update Information
// From cli.rs:903-908
println!("Update available for: {imgref:#}");
if let Some(version) = r.version() {
println!(" Version: {version}");
}
println!(" Digest: {}", r.manifest_digest);
Purpose: Display update information Information: Image reference, version, digest, changes
System Integration
1. Storage Management
// From cli.rs:861
let sysroot = &get_storage().await?;
Purpose: Get system storage interface Features: OSTree integration, filesystem management
2. Reboot Integration
// From cli.rs:962
crate::reboot::reboot()?;
Purpose: Reboot system after update Process: Trigger system reboot → Apply staged updates Features: Soft reboot support, reboot coordination
Performance Optimizations
1. Duplicate Detection
// From cli.rs:922-929
let staged_unchanged = staged_digest
.as_ref()
.map(|d| d == fetched_digest)
.unwrap_or_default();
let booted_unchanged = booted_image
.as_ref()
.map(|img| &img.manifest_digest == fetched_digest)
.unwrap_or_default();
Purpose: Avoid unnecessary downloads Process: Compare digests → Skip if unchanged Benefits: Reduced bandwidth, faster execution
2. Incremental Updates
// From cli.rs:917
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
Purpose: Download only changed layers Process: Registry comparison → Layer download → OSTree import Benefits: Reduced bandwidth, faster updates
Security Features
1. Signature Verification
// From cli.rs:917
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
Purpose: Verify image signatures Process: Registry authentication → Signature verification → Image validation Features: Cryptographic verification, trust validation
2. Image Validation
// From cli.rs:902
crate::deploy::check_bootc_label(&r.config);
Purpose: Validate image compatibility Process: Check bootc labels → Verify configuration → Validate compatibility Features: Label verification, configuration validation
Future Enhancements
1. Planned Features
- Userspace Restart: For kernel-unchanged updates
- Delta Updates: More efficient layer downloads
- Rollback Automation: Automatic rollback on failure
- Update Scheduling: Time-based update application
2. Integration Improvements
- API Support: REST API for update management
- Webhook Integration: Event notifications
- Metrics Collection: Update performance metrics
- Dashboard Integration: Web-based management
This technical reference provides comprehensive understanding of the bootc upgrade system's architecture, implementation, and integration patterns.