apt-ostree/.notes/client-daemon/apt-ostree.md
robojerk d295f9bb4d Major milestone: Complete apt-ostree bootc compatibility and OCI integration
-  Real package installation (replaced mock installation)
-  Real OSTree commit creation from installed packages
-  OCI image creation from both commits and rootfs
-  Full bootc compatibility with proper labels
-  Comprehensive test suite (test-bootc-apt-ostree.sh)
-  Container tool validation (skopeo, podman)
-  Updated compatibility reports for Ubuntu Questing
-  Fixed OCI schema version and field naming issues
-  Temporary directory lifecycle fixes
-  Serde rename attributes for OCI JSON compliance

Ready for Aurora-style workflow deployment!
2025-07-20 21:06:44 +00:00

24 KiB

apt-ostree Client-Daemon Architecture

Executive Summary

apt-ostree implements the same sophisticated client-daemon architecture as rpm-ostree, providing security, reliability, and concurrent operation support while maintaining 100% compatibility with the rpm-ostree interface. The architecture separates privileged system operations from unprivileged user interactions.

Architecture Overview

High-Level Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   CLI Client    │    │   GUI Client    │    │   API Client    │
│  (apt-ostree)   │    │  (GNOME/KDE)    │    │  (Python/Go)   │
└─────────┬───────┘    └─────────┬───────┘    └─────────┬───────┘
          │                      │                      │
          └──────────────────────┼──────────────────────┘
                                 │
                    ┌─────────────▼─────────────┐
                    │      D-Bus Interface      │
                    │   (org.aptostree.dev)     │
                    └─────────────┬─────────────┘
                                  │
                    ┌─────────────▼─────────────┐
                    │   apt-ostreed Daemon      │
                    │   (Privileged Service)    │
                    └─────────────┬─────────────┘
                                  │
          ┌───────────────────────┼───────────────────────┐
          │                       │                       │
    ┌─────▼─────┐         ┌───────▼──────┐         ┌─────▼─────┐
    │ libapt-pkg│         │   libostree  │         │  System   │
    │ (APT/DEB) │         │ (Filesystem) │         │ Services  │
    └───────────┘         └──────────────┘         └───────────┘

Design Principles

  1. Privilege Separation: Daemon runs with elevated privileges, clients run unprivileged
  2. D-Bus Communication: Standard system service interface for inter-process communication
  3. Transaction Management: Atomic operations with rollback capability
  4. Concurrent Operations: Multiple clients can interact simultaneously
  5. State Persistence: Daemon maintains system state across operations
  6. 100% Compatibility: Identical interface to rpm-ostree

Client Architecture

CLI Client (apt-ostree)

Purpose: Command-line interface for user interaction

Key Components:

  • Command Parser: Parse command-line arguments
  • D-Bus Client: Communicate with daemon
  • Progress Handler: Display operation progress
  • Error Handler: Handle and display errors
  • Fallback Handler: Direct system calls if daemon fails

Implementation:

pub struct AptOstreeClient {
    // D-Bus client
    connection: Option<Connection>,
    
    // Command dispatch
    pub fn execute_command(&mut self, args: &[String]) -> Result<(), Error>;
    
    // D-Bus communication
    pub fn connect_to_daemon(&mut self) -> Result<(), Error>;
    pub fn call_daemon_method(&mut self, method: &str, params: &[&str]) -> Result<(), Error>;
    
    // Fallback handling
    pub fn fallback_to_direct_calls(&mut self, args: &[String]) -> Result<(), Error>;
    
    // Progress handling
    pub fn handle_progress(&self, message: &str, percentage: i32);
    pub fn handle_completion(&self, success: bool, result: &str);
}

Command Flow:

  1. Parse command-line arguments
  2. Try to connect to daemon via D-Bus
  3. If daemon available: Send operation request
  4. If daemon unavailable: Use direct system calls
  5. Handle progress updates
  6. Display results or errors

GUI Clients (Planned)

Purpose: Graphical user interfaces for system management

Components:

  • GNOME Software: Integration with GNOME Software Center
  • KDE Discover: Integration with KDE Discover
  • Custom GUIs: Third-party graphical interfaces

Implementation:

  • Use D-Bus interface for system operations
  • Provide user-friendly progress indicators
  • Handle authentication via PolicyKit
  • Display system status and deployment information

API Clients (Planned)

Purpose: Programmatic interfaces for automation and integration

Components:

  • Python Bindings: Python library for apt-ostree operations
  • Go Bindings: Go library for apt-ostree operations
  • REST APIs: HTTP-based interfaces

Implementation:

  • Direct D-Bus communication
  • High-level abstractions for common operations
  • Error handling and recovery mechanisms
  • Async operation support

Daemon Architecture

Core Daemon (apt-ostreed)

Purpose: Centralized system service for privileged operations

Key Components:

  • D-Bus Service: Expose system management interface
  • Transaction Manager: Handle atomic operations
  • State Manager: Maintain system state
  • Resource Manager: Manage system resources
  • OSTree Detection: Environment validation

Implementation:

pub struct AptOstreeDaemon {
    // System integration
    package_manager: PackageManager,
    
    // Transaction management
    transactions: HashMap<String, Transaction>,
    
    // D-Bus interface
    connection: Option<Connection>,
    object_manager: Option<ObjectManager>,
    
    // OSTree detection
    ostree_detection: OstreeDetection,
    
    // Service management
    pub fn start_service(&mut self) -> Result<(), Error>;
    pub fn stop_service(&mut self) -> Result<(), Error>;
    pub fn handle_client_connection(&mut self, connection: Connection) -> Result<(), Error>;
}

Service Lifecycle:

  1. Initialize system components
  2. Validate OSTree environment
  3. Register D-Bus service
  4. Start listening for client connections
  5. Handle client requests
  6. Clean up on shutdown

D-Bus Interface

Service Name: org.aptostree.dev

Main Objects:

  • /org/aptostree/dev/Sysroot: System root management
  • /org/aptostree/dev/OS: Operating system operations

Key Methods:

<interface name="org.aptostree.dev.OS">
    <method name="install_packages">
        <arg name="packages" type="as" direction="in"/>
        <arg name="options" type="a{sv}" direction="in"/>
        <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="remove_packages">
        <arg name="packages" type="as" direction="in"/>
        <arg name="options" type="a{sv}" direction="in"/>
        <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="upgrade_system">
        <arg name="options" type="a{sv}" direction="in"/>
        <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="rollback">
        <arg name="options" type="a{sv}" direction="in"/>
        <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="show_status">
        <arg name="options" type="a{sv}" direction="in"/>
        <arg name="status" type="s" direction="out"/>
    </method>
    
    <method name="list_packages">
        <arg name="options" type="a{sv}" direction="in"/>
        <arg name="packages" type="as" direction="out"/>
    </method>
    
    <method name="search_packages">
        <arg name="query" type="s" direction="in"/>
        <arg name="options" type="a{sv}" direction="in"/>
        <arg name="results" type="as" direction="out"/>
    </method>
    
    <method name="show_package_info">
        <arg name="package" type="s" direction="in"/>
        <arg name="info" type="s" direction="out"/>
    </method>
</interface>

Signals:

<signal name="TransactionChanged">
    <arg name="transaction_address" type="s"/>
    <arg name="state" type="s"/>
    <arg name="message" type="s"/>
    <arg name="percentage" type="i"/>
</signal>

<signal name="TransactionCompleted">
    <arg name="transaction_address" type="s"/>
    <arg name="success" type="b"/>
    <arg name="result" type="s"/>
</signal>

Transaction Management

Purpose: Handle atomic operations with rollback capability

Transaction Types:

  1. InstallTransaction: Package installation with atomic commits
  2. RemoveTransaction: Package removal with rollback support
  3. UpgradeTransaction: System upgrades with automatic policies
  4. RollbackTransaction: Deployment rollback

Implementation:

pub struct Transaction {
    // Transaction state
    state: TransactionState,
    transaction_id: String,
    transaction_type: TransactionType,
    
    // Rollback information
    rollback_points: Vec<RollbackPoint>,
    
    // Progress reporting
    pub fn emit_progress(&self, message: &str, percentage: i32);
    pub fn emit_completion(&self, success: bool, result: &str);
    
    // Atomic execution
    pub fn execute_atomic(&mut self) -> Result<(), Error>;
    pub fn rollback_on_failure(&mut self) -> Result<(), Error>;
    
    // State management
    pub fn set_state(&mut self, new_state: TransactionState);
    pub fn get_state(&self) -> TransactionState;
}

Transaction Lifecycle:

  1. Initiation: Client requests operation
  2. Validation: Validate request parameters and OSTree environment
  3. Preparation: Set up rollback points
  4. Execution: Perform operation with progress reporting
  5. Completion: Finalize operation or rollback
  6. Cleanup: Clean up resources

State Management

Purpose: Maintain system state across operations

State Components:

  • Deployment State: Current and available deployments
  • Package State: Installed and layered packages
  • Configuration State: System configuration
  • Transaction State: Active and completed transactions

Implementation:

pub struct StateManager {
    // System state
    deployment_state: DeploymentState,
    package_state: PackageState,
    config_state: ConfigurationState,
    
    // State persistence
    pub fn save_state(&self) -> Result<(), Error>;
    pub fn load_state(&mut self) -> Result<(), Error>;
    pub fn sync_state(&mut self) -> Result<(), Error>;
    
    // State queries
    pub fn get_current_deployment(&self) -> Result<DeploymentInfo, Error>;
    pub fn get_available_deployments(&self) -> Result<Vec<DeploymentInfo>, Error>;
    pub fn get_installed_packages(&self) -> Result<Vec<PackageInfo>, Error>;
}

Communication Protocol

D-Bus Communication

Connection Setup:

// Client connection
let connection = Connection::new_system_sync()?;

// Service registration
let object_manager = ObjectManager::new("/org/aptostree/dev");

Method Calls:

// Client method call
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "install_packages",
    &(packages, options),
)?;

Signal Handling:

// Client signal connection
connection.add_match(
    "type='signal',interface='org.aptostree.dev.OS',member='TransactionChanged'",
)?;

// Signal handler
connection.add_signal_handler(
    "org.aptostree.dev.OS",
    "TransactionChanged",
    move |msg: &Message| {
        // Handle transaction change
        Ok(())
    },
)?;

Error Handling

Error Types:

  1. Network Errors: Package download failures
  2. Dependency Errors: Package dependency conflicts
  3. Filesystem Errors: OSTree operation failures
  4. Permission Errors: Insufficient privileges
  5. Transaction Errors: Transaction failures
  6. OSTree Environment Errors: Non-OSTree system

Error Propagation:

// Daemon error handling
fn handle_error(error: &str, invocation: &MethodInvocation) -> Result<(), Error> {
    invocation.return_error(
        "org.aptostree.dev.Error",
        error,
    )
}

// Client error handling
fn handle_daemon_error(error: &Error) {
    eprintln!("Error: {}", error);
    
    // Provide user guidance based on error type
    match error.kind() {
        ErrorKind::DaemonUnavailable => {
            eprintln!("Daemon is not running. Using direct system calls.");
        }
        ErrorKind::OstreeEnvironment => {
            eprintln!("This system is not running on an OSTree deployment.");
        }
        _ => {}
    }
}

Security Model

Privilege Separation

Principle: Separate privileged operations from unprivileged user operations

Implementation:

  • Daemon: Runs with elevated privileges (root)
  • Client: Runs with user privileges
  • D-Bus: Secure communication channel
  • PolicyKit: Authentication for privileged operations

Authentication

PolicyKit Integration:

<policyconfig>
    <action id="org.aptostree.dev.upgrade">
        <description>Upgrade system</description>
        <message>Authentication is required to upgrade the system</message>
        <defaults>
            <allow_any>auth_admin</allow_any>
            <allow_inactive>auth_admin</allow_inactive>
            <allow_active>auth_admin</allow_active>
        </defaults>
        <annotate key="org.freedesktop.policykit.exec.path">/usr/libexec/apt-ostreed</annotate>
    </action>
</policyconfig>

Bubblewrap Sandboxing

Package Script Execution:

  • Execute package scripts in controlled environment
  • Use namespace isolation for security
  • Restrict filesystem access
  • Limit privilege escalation

Implementation:

pub struct BubblewrapSandbox {
    // Sandbox configuration
    namespaces: Vec<Namespace>,
    bind_mounts: Vec<BindMount>,
    security_options: Vec<SecurityOption>,
    
    // Script execution
    pub fn execute_script(&self, script: &str, context: &ScriptContext) -> Result<(), Error>;
    
    // Security controls
    pub fn set_namespace_isolation(&mut self, enabled: bool);
    pub fn add_bind_mount(&mut self, source: &str, target: &str, read_only: bool);
    pub fn set_privilege_restrictions(&mut self, restrictions: Vec<PrivilegeRestriction>);
}

OSTree Environment Detection

Detection Methods

apt-ostree automatically detects if it's running in an OSTree environment using multiple methods:

  1. Filesystem Detection: Check for /ostree directory
  2. Boot Detection: Check for /run/ostree-booted file
  3. Kernel Parameter Detection: Check for ostree in /proc/cmdline
  4. Library Detection: Try to load OSTree sysroot
  5. Service Detection: Check for daemon availability

Implementation:

pub struct OstreeDetection {
    // Detection methods
    pub fn detect_filesystem(&self) -> bool;
    pub fn detect_boot(&self) -> bool;
    pub fn detect_kernel_params(&self) -> bool;
    pub fn detect_library(&self) -> bool;
    pub fn detect_service(&self) -> bool;
    
    // Comprehensive detection
    pub fn detect_ostree_environment(&self) -> Result<bool, Error>;
    
    // Error reporting
    pub fn get_detection_error(&self) -> String;
}

Error Handling

When not running in an OSTree environment, apt-ostree provides clear error messages:

Error: apt-ostree requires an OSTree environment to operate.

This system does not appear to be running on an OSTree deployment.

To use apt-ostree:
1. Ensure you are running on an OSTree-based system
2. Verify that /ostree directory exists
3. Verify that /run/ostree-booted file exists
4. Ensure you have a valid booted deployment

Concurrent Operations

Multiple Clients

Support: Multiple clients can interact with daemon simultaneously

Implementation:

  • Thread-Safe Operations: All operations are thread-safe
  • Transaction Isolation: Each operation gets its own transaction
  • Resource Locking: Prevent conflicting operations
  • Queue Management: Queue operations when necessary

Operation Queuing

Queue Management:

pub struct OperationQueue {
    pending_operations: VecDeque<Operation>,
    queue_mutex: Mutex<()>,
    queue_cv: Condvar,
    
    pub fn enqueue_operation(&mut self, operation: Operation);
    pub fn dequeue_operation(&mut self) -> Option<Operation>;
    pub fn has_pending_operations(&self) -> bool;
}

Performance Optimization

Resource Management

Memory Management:

  • Efficient memory usage for large operations
  • Garbage collection for completed transactions
  • Memory pooling for frequently allocated objects

Disk Management:

  • OSTree deduplication for storage efficiency
  • Temporary file cleanup
  • Cache management for package downloads

Network Optimization:

  • Parallel package downloads via APT
  • Connection pooling
  • Bandwidth optimization

Caching

Package Cache:

  • Cache downloaded packages via APT
  • Cache package metadata
  • Cache dependency resolution results

State Cache:

  • Cache deployment information
  • Cache package lists
  • Cache configuration data

Monitoring and Logging

Logging

Log Levels:

  • DEBUG: Detailed debugging information
  • INFO: General information
  • WARNING: Warning messages
  • ERROR: Error messages
  • CRITICAL: Critical errors

Log Implementation:

pub struct Logger {
    pub fn debug(&self, message: &str);
    pub fn info(&self, message: &str);
    pub fn warning(&self, message: &str);
    pub fn error(&self, message: &str);
    pub fn critical(&self, message: &str);
}

Monitoring

Health Monitoring:

  • Daemon health checks
  • Transaction monitoring
  • Resource usage monitoring
  • Error rate monitoring

Metrics Collection:

  • Operation success rates
  • Performance metrics
  • Resource usage statistics
  • Error statistics

Systemd Integration

Service Definition

Service File: /usr/lib/systemd/system/apt-ostreed.service

[Unit]
Description=apt-ostree Daemon
Documentation=man:apt-ostreed(8)
After=network.target

[Service]
Type=dbus
BusName=org.aptostree.dev
ExecStart=/usr/libexec/apt-ostreed
Restart=on-failure
RestartSec=1
User=root
Group=root

[Install]
WantedBy=multi-user.target
Also=apt-ostreed.socket

D-Bus Activation

Socket File: /usr/lib/systemd/system/apt-ostreed.socket

[Unit]
Description=apt-ostree D-Bus Socket
Documentation=man:apt-ostreed(8)

[Socket]
ListenStream=/run/dbus/system_bus_socket
SocketUser=root
SocketGroup=root

[Install]
WantedBy=sockets.target

Error Recovery

Automatic Recovery

Transaction Rollback:

  • Automatic rollback on transaction failure
  • State restoration to previous known good state
  • Resource cleanup after rollback

Daemon Recovery:

  • Automatic daemon restart on failure
  • State recovery on daemon restart
  • Transaction recovery for incomplete operations

Manual Recovery

Recovery Procedures:

  • Manual rollback procedures
  • State reset procedures
  • Configuration recovery procedures
  • Filesystem recovery procedures

APT Integration

APT Database Management

Purpose: Manage APT database in OSTree context

Implementation:

pub struct AptDatabaseManager {
    // APT integration
    cache: Option<*mut apt_pkg_Cache>,
    depcache: Option<*mut apt_pkg_DepCache>,
    
    // Database operations
    pub fn initialize_database(&mut self) -> Result<(), Error>;
    pub fn update_database(&mut self) -> Result<(), Error>;
    pub fn sync_database(&mut self) -> Result<(), Error>;
    
    // Package tracking
    pub fn track_package(&mut self, package: &str) -> Result<(), Error>;
    pub fn untrack_package(&mut self, package: &str) -> Result<(), Error>;
    pub fn get_tracked_packages(&self) -> Result<Vec<String>, Error>;
}

Package Management

Purpose: Handle APT package operations in OSTree context

Implementation:

pub struct AptPackageManager {
    // APT integration
    database_manager: AptDatabaseManager,
    
    // Package operations
    pub fn install_packages(&mut self, packages: &[String]) -> Result<(), Error>;
    pub fn remove_packages(&mut self, packages: &[String]) -> Result<(), Error>;
    pub fn upgrade_system(&mut self) -> Result<(), Error>;
    
    // Package information
    pub fn list_packages(&self) -> Result<Vec<PackageInfo>, Error>;
    pub fn search_packages(&self, query: &str) -> Result<Vec<PackageInfo>, Error>;
    pub fn show_package_info(&self, package: &str) -> Result<PackageInfo, Error>;
}

Future Enhancements

Planned Features

  1. Container Integration: Direct container support
  2. Cloud Integration: Cloud deployment support
  3. Advanced Monitoring: Enhanced monitoring capabilities
  4. Performance Optimization: Further performance improvements

Architecture Improvements

  1. Microservices: Split daemon into microservices
  2. API Gateway: REST API gateway for external access
  3. Event Streaming: Event streaming for real-time updates
  4. Distributed Operations: Support for distributed operations

APT Enhancements

  1. Advanced Dependency Resolution: Enhanced dependency handling
  2. Package Conflict Resolution: Improved conflict resolution
  3. Repository Management: Enhanced repository management
  4. Package Verification: Enhanced package verification

Daemon Setup and Testing

Installation and Setup

# Install daemon binary
sudo cp target/release/apt-ostreed /usr/libexec/

# Install D-Bus configuration
sudo cp src/daemon/org.aptostree.dev.conf /etc/dbus-1/system.d/

# Install systemd service
sudo cp src/daemon/apt-ostreed.service /etc/systemd/system/

# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable apt-ostreed
sudo systemctl start apt-ostreed

D-Bus Testing Commands

# Check daemon status
systemctl status apt-ostreed.service

# List D-Bus services
gdbus list --system | grep aptostree

# Test D-Bus introspection
gdbus introspect --system --dest org.aptostree.dev --object-path /org/aptostree/dev

# Test Ping method
gdbus call --system --dest org.aptostree.dev --object-path /org/aptostree/dev --method org.aptostree.dev.Daemon.Ping

# Test client-daemon communication
apt-ostree daemon-ping
apt-ostree daemon-status

Troubleshooting

# Check daemon logs
journalctl -u apt-ostreed.service --no-pager -n 20

# Restart daemon
sudo systemctl restart apt-ostreed.service

# Test with authentication
pkexec gdbus call --system --dest org.aptostree.dev --object-path /org/aptostree/dev --method org.aptostree.dev.Daemon.Ping

Directory Structure

/usr/
├── bin/apt-ostree                    # Client binary
├── libexec/apt-ostreed               # Daemon binary
└── share/
    ├── dbus-1/system-services/
    │   └── org.aptostree.dev.service # D-Bus activation
    └── polkit-1/actions/
        └── org.aptostree.dev.policy  # Authorization policies

/etc/
├── apt-ostree/apt-ostreed.conf       # Daemon configuration
├── dbus-1/system.d/
│   └── org.aptostree.dev.conf        # D-Bus policy
└── systemd/system/
    ├── apt-ostreed.service           # Main daemon service
    ├── apt-ostree-bootstatus.service # Boot status service
    ├── apt-ostree-countme.service    # Usage reporting service
    ├── apt-ostree-countme.timer      # Weekly timer
    ├── apt-ostreed-automatic.service # Automatic updates
    └── apt-ostreed-automatic.timer   # Daily timer

/var/
├── lib/apt-ostree/                   # OSTree repository and state
├── cache/apt-ostree/                 # APT cache
└── log/apt-ostree/                   # Log files