diff --git a/src/apt-layer/config/apt-layer-settings.json b/src/apt-layer/config/apt-layer-settings.json index 84c49d7..cb92778 100644 --- a/src/apt-layer/config/apt-layer-settings.json +++ b/src/apt-layer/config/apt-layer-settings.json @@ -8,6 +8,26 @@ "audit_reporting": true, "layer_signing": true }, + "container_runtimes": { + "supported": ["skopeo", "podman", "docker", "systemd-nspawn"], + "preference_order": ["skopeo", "podman", "docker", "systemd-nspawn"], + "skopeo": { + "description": "OCI-focused container operations", + "primary_use": "oci_integration" + }, + "podman": { + "description": "Rootless container runtime", + "primary_use": "general" + }, + "docker": { + "description": "Traditional container runtime", + "primary_use": "general" + }, + "systemd-nspawn": { + "description": "Systemd-based container runtime", + "primary_use": "fallback" + } + }, "log_level": "info", "color_output": true } \ No newline at end of file diff --git a/src/apt-layer/scriptlets/00-header.sh b/src/apt-layer/scriptlets/00-header.sh index 8daed57..4c28f84 100644 --- a/src/apt-layer/scriptlets/00-header.sh +++ b/src/apt-layer/scriptlets/00-header.sh @@ -70,7 +70,8 @@ BUILD_DIR="/var/lib/particle-os/build" LIVE_OVERLAY_DIR="/var/lib/particle-os/live-overlay" COMPOSEFS_DIR="/var/lib/particle-os/composefs" COMPOSEFS_SCRIPT="/usr/local/bin/composefs-alternative.sh" -CONTAINER_RUNTIME="podman" +# Container runtime will be detected dynamically based on configuration +CONTAINER_RUNTIME="" # Transaction state variables TRANSACTION_ID="" @@ -515,14 +516,14 @@ get_system_info() { echo "Architecture: $(uname -m)" echo "Available modules:" if modprobe -n squashfs >/dev/null 2>&1; then - echo " â squashfs module available" + echo " � squashfs module available" else - echo " â squashfs module not available" + echo " � squashfs module not available" fi if modprobe -n overlay >/dev/null 2>&1; then - echo " â overlay module available" + echo " � overlay module available" else - echo " â overlay module not available" + echo " � overlay module not available" fi } diff --git a/src/apt-layer/scriptlets/02-transactions.sh b/src/apt-layer/scriptlets/02-transactions.sh index cc0e870..98d7f9f 100644 --- a/src/apt-layer/scriptlets/02-transactions.sh +++ b/src/apt-layer/scriptlets/02-transactions.sh @@ -84,8 +84,8 @@ export APT_LAYER_LOG_FILE="$APT_LAYER_LOG_DIR/apt-layer.log" export APT_LAYER_SIGNING_ENABLED="false" export APT_LAYER_VERIFY_SIGNATURES="false" -# Container settings -export APT_LAYER_CONTAINER_RUNTIME="podman" +# Container settings - will be set dynamically +export APT_LAYER_CONTAINER_RUNTIME="" export APT_LAYER_CHROOT_ENABLED="true" # Default package sources diff --git a/src/apt-layer/scriptlets/04-container.sh b/src/apt-layer/scriptlets/04-container.sh index d304e98..02b9aac 100644 --- a/src/apt-layer/scriptlets/04-container.sh +++ b/src/apt-layer/scriptlets/04-container.sh @@ -6,28 +6,86 @@ detect_container_runtime() { log_info "Detecting container runtime" "apt-layer" - # Check for podman first (preferred for rootless) + # Get configured default runtime + local configured_runtime + if [[ -f "$CONFIG_DIR/apt-layer-settings.json" ]]; then + configured_runtime=$(jq -r '.default_container_runtime // empty' "$CONFIG_DIR/apt-layer-settings.json" 2>/dev/null) + fi + + # If configured runtime is specified and available, use it + if [[ -n "$configured_runtime" ]]; then + case "$configured_runtime" in + podman) + if command -v podman &> /dev/null; then + CONTAINER_RUNTIME="podman" + log_info "Using configured container runtime: podman" "apt-layer" + return 0 + else + log_warning "Configured runtime 'podman' not found, falling back to detection" "apt-layer" + fi + ;; + docker) + if command -v docker &> /dev/null; then + CONTAINER_RUNTIME="docker" + log_info "Using configured container runtime: docker" "apt-layer" + return 0 + else + log_warning "Configured runtime 'docker' not found, falling back to detection" "apt-layer" + fi + ;; + systemd-nspawn) + if command -v systemd-nspawn &> /dev/null; then + CONTAINER_RUNTIME="systemd-nspawn" + log_info "Using configured container runtime: systemd-nspawn" "apt-layer" + return 0 + else + log_warning "Configured runtime 'systemd-nspawn' not found, falling back to detection" "apt-layer" + fi + ;; + skopeo) + if command -v skopeo &> /dev/null; then + CONTAINER_RUNTIME="skopeo" + log_info "Using configured container runtime: skopeo" "apt-layer" + return 0 + else + log_warning "Configured runtime 'skopeo' not found, falling back to detection" "apt-layer" + fi + ;; + esac + fi + + # Auto-detection fallback (in order of preference) + log_info "Auto-detecting container runtime" "apt-layer" + + # Check for skopeo first (preferred for OCI operations) + if command -v skopeo &> /dev/null; then + CONTAINER_RUNTIME="skopeo" + log_info "Auto-detected skopeo as container runtime" "apt-layer" + return 0 + fi + + # Check for podman (preferred for rootless) if command -v podman &> /dev/null; then CONTAINER_RUNTIME="podman" - log_info "Using podman as container runtime" "apt-layer" + log_info "Auto-detected podman as container runtime" "apt-layer" return 0 fi # Fallback to docker if command -v docker &> /dev/null; then CONTAINER_RUNTIME="docker" - log_info "Using docker as container runtime" "apt-layer" + log_info "Auto-detected docker as container runtime" "apt-layer" return 0 fi # Check for systemd-nspawn as last resort if command -v systemd-nspawn &> /dev/null; then CONTAINER_RUNTIME="systemd-nspawn" - log_info "Using systemd-nspawn as container runtime" "apt-layer" + log_info "Auto-detected systemd-nspawn as container runtime" "apt-layer" return 0 fi - log_error "No supported container runtime found (podman, docker, or systemd-nspawn)" "apt-layer" + log_error "No supported container runtime found (skopeo, podman, docker, or systemd-nspawn)" "apt-layer" return 1 } @@ -45,6 +103,9 @@ init_container_system() { return 1 fi + # Set global container runtime variables + set_global_container_runtime_vars + # Ensure workspace directories exist mkdir -p "$WORKSPACE"/{images,temp,containers} @@ -52,6 +113,37 @@ init_container_system() { return 0 } +# Set global container runtime variables +set_global_container_runtime_vars() { + log_debug "Setting global container runtime variables" "apt-layer" + + # Set variables used throughout the system + export APT_LAYER_CONTAINER_RUNTIME="$CONTAINER_RUNTIME" + export PARTICLE_CONTAINER_RUNTIME="$CONTAINER_RUNTIME" + + # Set runtime-specific variables + case "$CONTAINER_RUNTIME" in + skopeo) + export CONTAINER_RUNTIME_TYPE="oci" + export CONTAINER_RUNTIME_DESCRIPTION="OCI-focused container operations" + ;; + podman) + export CONTAINER_RUNTIME_TYPE="general" + export CONTAINER_RUNTIME_DESCRIPTION="Rootless container runtime" + ;; + docker) + export CONTAINER_RUNTIME_TYPE="general" + export CONTAINER_RUNTIME_DESCRIPTION="Traditional container runtime" + ;; + systemd-nspawn) + export CONTAINER_RUNTIME_TYPE="fallback" + export CONTAINER_RUNTIME_DESCRIPTION="Systemd-based container runtime" + ;; + esac + + log_debug "Container runtime variables set: $CONTAINER_RUNTIME ($CONTAINER_RUNTIME_TYPE)" "apt-layer" +} + # Validate container runtime capabilities validate_container_runtime() { local runtime="$1" @@ -59,6 +151,12 @@ validate_container_runtime() { log_info "Validating container runtime: $runtime" "apt-layer" case "$runtime" in + skopeo) + if ! skopeo --version &> /dev/null; then + log_error "skopeo is not properly configured" "apt-layer" + return 1 + fi + ;; podman) if ! podman info &> /dev/null; then log_error "podman is not properly configured" "apt-layer" @@ -205,6 +303,12 @@ container_install_packages() { # Run package installation in container case "$CONTAINER_RUNTIME" in + skopeo) + if ! run_skopeo_install "$base_image" "$container_name" "$temp_dir" "${packages[@]}"; then + rollback_transaction + return 1 + fi + ;; podman) if ! run_podman_install "$base_image" "$container_name" "$temp_dir" "${packages[@]}"; then rollback_transaction @@ -241,6 +345,49 @@ container_install_packages() { return 0 } +# Skopeo-based package installation (OCI-focused) +run_skopeo_install() { + local base_image="$1" + local container_name="$2" + local temp_dir="$3" + shift 3 + local packages=("$@") + + log_info "Running skopeo-based installation" "apt-layer" + + # Skopeo is primarily for OCI operations, so we'll use it with a minimal container + # For package installation, we'll fall back to a chroot-based approach + + # Create minimal container structure + mkdir -p "$temp_dir"/{bin,lib,lib64,usr,etc,var} + + # Set up base filesystem + if [[ -d "$WORKSPACE/images/$base_image" ]]; then + # Use ComposeFS image as base + log_info "Using ComposeFS image as base for skopeo" "apt-layer" + cp -a "$WORKSPACE/images/$base_image"/* "$temp_dir/" 2>/dev/null || true + else + # Use minimal Ubuntu base + log_info "Using minimal Ubuntu base for skopeo" "apt-layer" + # Copy essential files + cp -a /bin/bash "$temp_dir/bin/" + cp -a /lib/x86_64-linux-gnu "$temp_dir/lib/" + cp -a /usr/bin/apt-get "$temp_dir/usr/bin/" + # Add minimal /etc structure + echo "deb http://archive.ubuntu.com/ubuntu/ jammy main" > "$temp_dir/etc/apt/sources.list" + fi + + # Install packages using chroot + local install_cmd="apt-get update && apt-get install -y ${packages[*]} && apt-get clean" + if ! chroot "$temp_dir" /bin/bash -c "$install_cmd"; then + log_error "Package installation failed in skopeo container" "apt-layer" + return 1 + fi + + log_success "Skopeo-based installation completed" "apt-layer" + return 0 +} + # Podman-based package installation run_podman_install() { local base_image="$1" @@ -558,6 +705,10 @@ container_status() { echo "Runtime: $CONTAINER_RUNTIME" case "$CONTAINER_RUNTIME" in + skopeo) + echo "Skopeo version: $(skopeo --version 2>/dev/null || echo 'Not available')" + echo "Skopeo info: OCI-focused container operations" + ;; podman) echo "Podman version: $(podman --version 2>/dev/null || echo 'Not available')" echo "Podman info: $(podman info --format json 2>/dev/null | jq -r '.host.arch // "Unknown"' 2>/dev/null || echo 'Unknown')" diff --git a/src/apt-layer/scriptlets/24-dpkg-direct-install.sh b/src/apt-layer/scriptlets/24-dpkg-direct-install.sh index 38e13af..d03e6aa 100644 --- a/src/apt-layer/scriptlets/24-dpkg-direct-install.sh +++ b/src/apt-layer/scriptlets/24-dpkg-direct-install.sh @@ -153,6 +153,12 @@ container_dpkg_install() { # Run dpkg installation in container case "$CONTAINER_RUNTIME" in + skopeo) + if ! run_skopeo_dpkg_install "$base_image" "$container_name" "$temp_dir" "${packages[@]}"; then + rollback_transaction + return 1 + fi + ;; podman) if ! run_podman_dpkg_install "$base_image" "$container_name" "$temp_dir" "${packages[@]}"; then rollback_transaction @@ -209,6 +215,56 @@ container_dpkg_install() { return 0 } +# Skopeo-based dpkg installation (OCI-focused) +run_skopeo_dpkg_install() { + local base_image="$1" + local container_name="$2" + local temp_dir="$3" + shift 3 + local packages=("$@") + + log_info "Running skopeo-based dpkg installation" "apt-layer" + + # Skopeo is primarily for OCI operations, so we'll use chroot for package installation + # Create minimal container structure + mkdir -p "$temp_dir"/{bin,lib,lib64,usr,etc,var} + + # Set up base filesystem + if [[ -d "$WORKSPACE/images/$base_image" ]]; then + # Use ComposeFS image as base + log_info "Using ComposeFS image as base for skopeo dpkg" "apt-layer" + cp -a "$WORKSPACE/images/$base_image"/* "$temp_dir/" 2>/dev/null || true + else + # Use minimal Ubuntu base + log_info "Using minimal Ubuntu base for skopeo dpkg" "apt-layer" + # Copy essential files + cp -a /bin/bash "$temp_dir/bin/" + cp -a /lib/x86_64-linux-gnu "$temp_dir/lib/" + cp -a /usr/bin/dpkg "$temp_dir/usr/bin/" + cp -a /usr/bin/apt-get "$temp_dir/usr/bin/" + # Add minimal /etc structure + echo "deb http://archive.ubuntu.com/ubuntu/ jammy main" > "$temp_dir/etc/apt/sources.list" + fi + + # Download and install packages using dpkg + local install_cmd=" + apt-get update && + apt-get download ${packages[*]} && + dpkg -i *.deb && + apt-get install -f && + dpkg --configure -a && + apt-get clean + " + + if ! chroot "$temp_dir" /bin/bash -c "$install_cmd"; then + log_error "dpkg installation failed in skopeo container" "apt-layer" + return 1 + fi + + log_success "Skopeo-based dpkg installation completed" "apt-layer" + return 0 +} + # Podman-based dpkg installation run_podman_dpkg_install() { local base_image="$1" diff --git a/src/apt-layer/scriptlets/99-main.sh b/src/apt-layer/scriptlets/99-main.sh index a2e2bfd..f9fc74e 100644 --- a/src/apt-layer/scriptlets/99-main.sh +++ b/src/apt-layer/scriptlets/99-main.sh @@ -668,7 +668,8 @@ PARTICLE_COMPOSEFS_DIR="$PARTICLE_WORKSPACE/composefs" PARTICLE_COMPOSEFS_SCRIPT="/usr/local/bin/composefs-alternative.sh" # Container configuration -PARTICLE_CONTAINER_RUNTIME="podman" +# Container runtime will be detected dynamically +PARTICLE_CONTAINER_RUNTIME="" PARTICLE_CONTAINER_WORKSPACE="$PARTICLE_WORKSPACE/containers" # Live overlay configuration