# apt-ostree OSTree Implementation

## Overview

apt-ostree implements OSTree as its core filesystem management system, providing atomic, immutable deployments with APT/DEB package layering capabilities. This document explains how apt-ostree implements and extends OSTree functionality for Debian/Ubuntu systems.

## Core OSTree Integration

### Repository Management

apt-ostree maintains an OSTree repository at `/ostree/repo` that stores:
- **Content-addressable objects**: Files and metadata stored by SHA256 hash
- **Commits**: Immutable snapshots of filesystem trees
- **Refs**: Symbolic pointers to specific commits (e.g., `ubuntu/24.04/x86_64/desktop`)
- **Static deltas**: Pre-calculated differences between commits for efficient updates

### Deployment Structure

```
/ostree/
├── repo/                      # OSTree repository (content-addressable storage)
├── deploy/                    # Active deployments
│   └── ubuntu-desktop/        # State root for Ubuntu Desktop
│       ├── var/               # Shared mutable data across deployments
│       └── <checksum>/        # Individual deployment directories
└── boot/                      # Bootloader configuration
```

### Filesystem Assembly

apt-ostree assembles the live filesystem using:
- **Hardlinks**: Deployments use hardlinks to objects in `/ostree/repo`
- **Bind mounts**: Read-only `/usr` mounted from deployment
- **Symlinks**: User directories redirected to `/var`
- **3-way merge**: `/etc` merged from old deployment, new deployment, and local changes

## APT-OSTree Specific Extensions

### Package Layering

apt-ostree extends OSTree with APT/DEB package layering:

```rust
// Core layering implementation in src/ostree.rs
pub struct OstreeManager {
    repo: OstreeRepo,
    sysroot: OstreeSysroot,
}

impl OstreeManager {
    // Create new deployment with layered packages
    pub fn create_deployment_with_layers(
        &self,
        base_commit: &str,
        new_commit: &str,
        layered_packages: &[String],
    ) -> Result<(), Box<dyn std::error::Error>> {
        // 1. Extract base filesystem from OSTree commit
        let base_tree = self.repo.read_commit(base_commit, None)?;
        
        // 2. Apply DEB package layers
        let layered_tree = self.apply_deb_layers(&base_tree, layered_packages)?;
        
        // 3. Create new OSTree commit
        let new_commit_checksum = self.repo.write_commit(
            &layered_tree,
            "Package layer update",
            None,
            None,
        )?;
        
        // 4. Update ref to point to new commit
        self.repo.set_ref(None, "ubuntu/24.04/x86_64/desktop", &new_commit_checksum)?;
        
        Ok(())
    }
    
    // Apply DEB package layers to deployment
    pub fn apply_deb_layers(
        &self,
        base_tree: &OstreeRepoFile,
        packages: &[String],
    ) -> Result<OstreeRepoFile, Box<dyn std::error::Error>> {
        // Extract DEB packages and apply to filesystem tree
        for package in packages {
            let extracted_package = self.extract_deb_package(package)?;
            self.merge_package_into_tree(&base_tree, &extracted_package)?;
        }
        
        Ok(base_tree.clone())
    }
}
```

### Transaction Management

apt-ostree implements atomic transactions for all OSTree operations:

```rust
// Transaction types for OSTree operations
#[derive(Debug, Clone)]
pub enum TransactionType {
    Deploy,
    Rollback,
    PkgChange,
    Rebase,
    Upgrade,
}

// Transaction execution with OSTree integration
pub struct OstreeTransaction {
    transaction_type: TransactionType,
    sysroot: OstreeSysroot,
}

impl OstreeTransaction {
    // Execute transaction with OSTree commit creation
    pub fn execute_with_ostree_commit(
        &self,
        base_commit: &str,
        new_commit: &str,
    ) -> Result<(), Box<dyn std::error::Error>> {
        match self.transaction_type {
            TransactionType::Deploy => {
                self.create_deployment(base_commit, new_commit)?;
            }
            TransactionType::Rollback => {
                self.rollback_to_previous_deployment()?;
            }
            TransactionType::PkgChange => {
                self.apply_package_changes(base_commit, new_commit)?;
            }
            _ => {
                return Err("Unsupported transaction type".into());
            }
        }
        
        Ok(())
    }
    
    // Rollback to previous OSTree deployment
    pub fn rollback_to_previous_deployment(&self) -> Result<(), Box<dyn std::error::Error>> {
        let deployments = self.sysroot.get_deployments()?;
        if deployments.len() < 2 {
            return Err("No previous deployment available for rollback".into());
        }
        
        // Switch to previous deployment
        let previous_deployment = &deployments[1];
        self.sysroot.set_default_deployment(previous_deployment)?;
        
        Ok(())
    }
}
```

### OSTree Commit Creation

apt-ostree creates OSTree commits for all system changes:

```rust
// Commit creation workflow in src/ostree.rs
impl OstreeManager {
    pub fn create_commit(
        &self,
        base_commit: &str,
        new_commit: &str,
        subject: &str,
        layered_packages: &[String],
    ) -> Result<String, Box<dyn std::error::Error>> {
        // 1. Extract base filesystem from OSTree commit
        let base_tree = self.repo.read_commit(base_commit, None)?;
        
        // 2. Apply DEB package layers
        let layered_tree = self.apply_deb_layers(&base_tree, layered_packages)?;
        
        // 3. Create new OSTree commit
        let new_commit_checksum = self.repo.write_commit(
            &layered_tree,
            subject,
            None,
            None,
        )?;
        
        // 4. Update ref to point to new commit
        self.repo.set_ref(None, "ubuntu/24.04/x86_64/desktop", &new_commit_checksum)?;
        
        Ok(new_commit_checksum)
    }
}
```

## OSTree Environment Detection

apt-ostree detects OSTree environments using multiple methods:

```rust
// Environment detection in src/ostree_detection.rs
pub struct OstreeDetection;

impl OstreeDetection {
    pub fn is_ostree_environment() -> bool {
        // Method 1: Check for /ostree directory
        if !std::path::Path::new("/ostree").is_dir() {
            return false;
        }
        
        // Method 2: Check for /run/ostree-booted file
        if !std::path::Path::new("/run/ostree-booted").exists() {
            return false;
        }
        
        // Method 3: Check kernel command line for ostree parameter
        if let Ok(cmdline) = std::fs::read_to_string("/proc/cmdline") {
            if !cmdline.contains("ostree") {
                return false;
            }
        }
        
        // Method 4: Try to load OSTree sysroot
        if let Ok(sysroot) = OstreeSysroot::new_default() {
            if sysroot.load().is_ok() {
                return true;
            }
        }
        
        false
    }
    
    pub fn get_detection_methods() -> Vec<String> {
        vec![
            "Filesystem detection (/ostree directory)".to_string(),
            "Boot detection (/run/ostree-booted file)".to_string(),
            "Kernel parameter detection (ostree in /proc/cmdline)".to_string(),
            "Library detection (OSTree sysroot loading)".to_string(),
            "Service detection (daemon availability)".to_string(),
        ]
    }
}
```

## OSTree Integration Points

### Daemon Integration

The apt-ostree daemon integrates with OSTree for privileged operations:

```rust
// Daemon OSTree operations in src/bin/apt-ostreed.rs
pub struct AptOstreedDaemon {
    ostree_manager: OstreeManager,
}

impl AptOstreedDaemon {
    // OSTree deployment management
    pub fn deploy_ostree_commit(
        &self,
        commit_checksum: &str,
        osname: &str,
    ) -> Result<(), Box<dyn std::error::Error>> {
        self.ostree_manager.create_deployment(commit_checksum, osname)
    }
    
    // OSTree rollback operations
    pub fn rollback_ostree_deployment(
        &self,
        osname: &str,
    ) -> Result<(), Box<dyn std::error::Error>> {
        self.ostree_manager.rollback_deployment(osname)
    }
    
    // OSTree status reporting
    pub fn get_ostree_status(&self) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
        let deployments = self.ostree_manager.get_deployments()?;
        let current_deployment = self.ostree_manager.get_current_deployment()?;
        
        Ok(json!({
            "deployments": deployments,
            "current": current_deployment,
            "booted": self.ostree_manager.is_booted_deployment(&current_deployment)?,
        }))
    }
}
```

### CLI Integration

apt-ostree CLI commands integrate with OSTree operations:

```rust
// CLI command integration in src/main.rs
pub fn deploy_command(matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
    let commit = matches.get_one::<String>("COMMIT")
        .ok_or("No commit specified")?;
    
    // Create deployment via D-Bus daemon
    let client = AptOstreeClient::new()?;
    client.deploy(commit)?;
    
    println!("Deployment created successfully");
    Ok(())
}

pub fn rollback_command(_matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
    // Rollback via D-Bus daemon
    let client = AptOstreeClient::new()?;
    client.rollback()?;
    
    println!("Rollback completed successfully");
    Ok(())
}
```

## OSTree Performance Optimizations

### Static Delta Support

apt-ostree leverages OSTree static deltas for efficient updates:

```rust
// Static delta usage in src/ostree.rs
impl OstreeManager {
    pub fn pull_with_static_deltas(
        &self,
        remote_name: &str,
        refspec: &str,
    ) -> Result<(), Box<dyn std::error::Error>> {
        // Configure static delta usage
        self.repo.set_enable_static_deltas(true);
        
        // Pull with static delta optimization
        self.repo.pull(remote_name, refspec, None)
    }
}
```

### Content Deduplication

apt-ostree benefits from OSTree's content-addressable storage:

```rust
// Content deduplication example
impl OstreeManager {
    pub fn commit_with_deduplication(
        &self,
        base_commit: &str,
        new_commit: &str,
    ) -> Result<String, Box<dyn std::error::Error>> {
        // OSTree automatically deduplicates identical files
        // Only unique content is stored in the repository
        let base_tree = self.repo.read_commit(base_commit, None)?;
        
        // Create commit with automatic deduplication
        self.repo.write_commit(&base_tree, "Update", None, None)
    }
}
```

## OSTree Security Features

### GPG Signature Verification

apt-ostree verifies OSTree commits using GPG signatures:

```rust
// GPG verification in src/ostree.rs
impl OstreeManager {
    pub fn verify_commit_signature(
        &self,
        commit_checksum: &str,
    ) -> Result<bool, Box<dyn std::error::Error>> {
        // Verify commit signature
        let sign = OstreeSign::new()?;
        self.repo.verify_commit(commit_checksum, &sign)
    }
}
```

### Read-Only Filesystem Enforcement

apt-ostree enforces OSTree's read-only filesystem model:

```rust
// Read-only enforcement in src/system.rs
impl SystemManager {
    pub fn enforce_readonly_filesystem(
        &self,
        deployment_path: &str,
    ) -> Result<(), Box<dyn std::error::Error>> {
        // Mount /usr as read-only
        let mount_cmd = format!("mount --bind -o ro {} /usr", deployment_path);
        self.run_command(&mount_cmd)?;
        
        Ok(())
    }
}
```

## OSTree Integration Testing

### Deployment Testing

```bash
# Test OSTree deployment creation
apt-ostree deploy $(apt-ostree status --json | jq -r '.deployments[0].checksum')

# Test OSTree rollback
apt-ostree rollback

# Test OSTree status
apt-ostree status --json
```

### Performance Testing

```bash
# Test OSTree pull performance
time ostree pull ubuntu ubuntu/24.04/x86_64/desktop

# Test static delta usage
ostree pull --enable-static-deltas ubuntu ubuntu/24.04/x86_64/desktop

# Test commit creation performance
time apt-ostree install package-name
```

## OSTree Troubleshooting

### Common Issues

1. **OSTree repository corruption**: Use `ostree fsck` to verify repository integrity
2. **Deployment failures**: Check `/var/log/ostree.log` for detailed error messages
3. **Bootloader issues**: Verify GRUB configuration with `ostree admin boot`
4. **Space issues**: Use `ostree admin cleanup` to remove old deployments

### Debug Commands

```bash
# Check OSTree repository status
ostree fsck --repo=/ostree/repo

# List available deployments
ostree admin status

# Check bootloader configuration
ostree admin boot

# Verify commit signatures
ostree verify --repo=/ostree/repo ubuntu/24.04/x86_64/desktop
```

## OSTree Future Enhancements

### Planned Features

1. **Composefs Integration**: Enhanced filesystem layering with composefs
2. **OCI Container Support**: Direct OSTree to OCI container conversion
3. **Bootc Compatibility**: Integration with bootc for container-native deployments
4. **Enhanced Static Deltas**: Improved delta generation and application

### Integration Roadmap

- **Phase 1**: Core OSTree integration (✅ Complete)
- **Phase 2**: Performance optimizations (✅ Complete)
- **Phase 3**: Security enhancements (✅ Complete)
- **Phase 4**: OCI container support (🔄 In Progress)
- **Phase 5**: Bootc compatibility (📋 Planned)

## Ubuntu/Debian Specific Considerations

### Filesystem Layout

apt-ostree adapts OSTree for Ubuntu/Debian filesystem conventions:

```
/
├── ostree/                    # OSTree repository and deployments
│   ├── repo/                 # OSTree repository
│   ├── deploy/               # Deployed systems
│   └── boot/                 # Boot configurations
├── var/                      # Writable data (shared across deployments)
│   ├── home/                 # User home directories
│   ├── opt/                  # Optional application software
│   ├── usrlocal/             # Locally installed software
│   ├── etc/                  # System configuration (merged on upgrade)
│   └── tmp/                  # Temporary files
├── etc/                      # System configuration (writable)
└── usr/                      # Read-only system software
```

### Package Management Integration

apt-ostree integrates APT package management with OSTree:

```rust
// APT-OSTree integration in src/apt.rs
impl AptManager {
    pub fn install_packages_with_ostree(
        &self,
        packages: &[String],
    ) -> Result<(), Box<dyn std::error::Error>> {
        // 1. Download and extract DEB packages
        let extracted_packages = self.download_and_extract_packages(packages)?;
        
        // 2. Create OSTree commit with package layers
        let ostree_manager = OstreeManager::new()?;
        ostree_manager.create_commit_with_layers(
            &self.get_current_commit()?,
            "Package installation",
            &extracted_packages,
        )?;
        
        // 3. Deploy new commit
        ostree_manager.deploy_latest_commit()?;
        
        Ok(())
    }
}
```

### mmdebstrap Integration

apt-ostree uses mmdebstrap for efficient base system creation:

```bash
# Create base system with mmdebstrap
sudo mmdebstrap --arch=amd64 --variant=minbase \
    --include=systemd,systemd-sysv,ostree \
    noble /tmp/ubuntu-base

# Create package layer
sudo mmdebstrap --arch=amd64 \
    --include=ubuntu-desktop-minimal,gnome-shell \
    noble /tmp/ubuntu-desktop /tmp/ubuntu-base

# Create OSTree commit
sudo ostree commit --repo=/ostree/repo \
    --branch=ubuntu/24.04/x86_64/desktop \
    --parent=ubuntu/24.04/x86_64/base \
    /tmp/ubuntu-desktop
``` 