#!/bin/bash # Particle-OS Unified Configuration # This file provides consistent configuration for all Particle-OS scripts # Source this file in other scripts: source /usr/local/etc/particle-config.sh set -euo pipefail # ============================================================================= # CORE CONFIGURATION # ============================================================================= # Base directories PARTICLE_ROOT="/var/lib/particle-os" PARTICLE_CONFIG_DIR="/usr/local/etc/particle-os" PARTICLE_LOG_DIR="/var/log/particle-os" PARTICLE_CACHE_DIR="/var/cache/particle-os" # Script locations PARTICLE_SCRIPTS_DIR="/usr/local/bin" COMPOSEFS_SCRIPT="$PARTICLE_SCRIPTS_DIR/composefs" BOOTUPD_SCRIPT="$PARTICLE_SCRIPTS_DIR/bootupd" APT_LAYER_SCRIPT="$PARTICLE_SCRIPTS_DIR/apt-layer" # ComposeFS configuration COMPOSEFS_DIR="/var/lib/composefs-alternative" COMPOSEFS_IMAGES_DIR="$COMPOSEFS_DIR/images" COMPOSEFS_LAYERS_DIR="$COMPOSEFS_DIR/layers" COMPOSEFS_MOUNTS_DIR="$COMPOSEFS_DIR/mounts" # Build and workspace directories PARTICLE_BUILD_DIR="$PARTICLE_ROOT/build" PARTICLE_WORKSPACE_DIR="$PARTICLE_ROOT/workspace" PARTICLE_TEMP_DIR="$PARTICLE_ROOT/temp" # Live overlay configuration PARTICLE_LIVE_OVERLAY_DIR="$PARTICLE_ROOT/live-overlay" PARTICLE_LIVE_UPPER_DIR="$PARTICLE_LIVE_OVERLAY_DIR/upper" PARTICLE_LIVE_WORK_DIR="$PARTICLE_LIVE_OVERLAY_DIR/work" # Transaction management PARTICLE_TRANSACTION_LOG="$PARTICLE_LOG_DIR/transaction.log" PARTICLE_TRANSACTION_STATE="$PARTICLE_ROOT/transaction.state" PARTICLE_TRANSACTION_BACKUP_DIR="$PARTICLE_ROOT/backups" # ============================================================================= # LOGGING CONFIGURATION # ============================================================================= # Log levels: DEBUG, INFO, WARNING, ERROR PARTICLE_LOG_LEVEL="${PARTICLE_LOG_LEVEL:-INFO}" # Log file paths PARTICLE_MAIN_LOG="$PARTICLE_LOG_DIR/particle.log" COMPOSEFS_LOG="$PARTICLE_LOG_DIR/composefs.log" BOOTUPD_LOG="$PARTICLE_LOG_DIR/bootupd.log" APT_LAYER_LOG="$PARTICLE_LOG_DIR/apt-layer.log" # Log rotation settings PARTICLE_LOG_MAX_SIZE="100M" PARTICLE_LOG_MAX_FILES=5 PARTICLE_LOG_COMPRESSION="${PARTICLE_LOG_COMPRESSION:-gzip}" PARTICLE_LOG_FILES_PATTERN="${PARTICLE_LOG_FILES_PATTERN:-*.log}" # ============================================================================= # SECURITY CONFIGURATION # ============================================================================= # GPG key for signing PARTICLE_SIGNING_KEY="${PARTICLE_SIGNING_KEY:-}" PARTICLE_SIGNING_KEYRING="${PARTICLE_SIGNING_KEYRING:-/etc/apt/trusted.gpg}" # Secure Boot configuration PARTICLE_SECURE_BOOT_ENABLED="${PARTICLE_SECURE_BOOT_ENABLED:-false}" PARTICLE_SB_KEYS_DIR="$PARTICLE_CONFIG_DIR/secure-boot" # ============================================================================= # PERFORMANCE CONFIGURATION # ============================================================================= # Parallel processing PARTICLE_PARALLEL_JOBS="${PARTICLE_PARALLEL_JOBS:-$(nproc 2>/dev/null || echo 4)}" PARTICLE_MAX_PARALLEL_JOBS=8 # Compression settings PARTICLE_SQUASHFS_COMPRESSION="${PARTICLE_SQUASHFS_COMPRESSION:-xz}" PARTICLE_SQUASHFS_BLOCK_SIZE="${PARTICLE_SQUASHFS_BLOCK_SIZE:-1M}" # Cache settings PARTICLE_APT_CACHE_DIR="$PARTICLE_CACHE_DIR/apt" PARTICLE_CONTAINER_CACHE_DIR="$PARTICLE_CACHE_DIR/containers" # ============================================================================= # CONTAINER CONFIGURATION # ============================================================================= # Container runtime preference PARTICLE_CONTAINER_RUNTIME="${PARTICLE_CONTAINER_RUNTIME:-podman}" # Container registry settings PARTICLE_REGISTRY_URL="${PARTICLE_REGISTRY_URL:-}" PARTICLE_REGISTRY_USERNAME="${PARTICLE_REGISTRY_USERNAME:-}" PARTICLE_REGISTRY_PASSWORD="${PARTICLE_REGISTRY_PASSWORD:-}" # ============================================================================= # NETWORK CONFIGURATION # ============================================================================= # Package repository mirrors PARTICLE_APT_MIRRORS=( "http://archive.ubuntu.com/ubuntu/" "http://security.ubuntu.com/ubuntu/" ) # Proxy settings (if needed) PARTICLE_HTTP_PROXY="${PARTICLE_HTTP_PROXY:-}" PARTICLE_HTTPS_PROXY="${PARTICLE_HTTPS_PROXY:-}" PARTICLE_NO_PROXY="${PARTICLE_NO_PROXY:-localhost,127.0.0.1}" # ============================================================================= # VALIDATION FUNCTIONS # ============================================================================= # Validate configuration validate_particle_config() { local errors=0 # Check required directories for dir in "$PARTICLE_ROOT" "$PARTICLE_CONFIG_DIR" "$PARTICLE_LOG_DIR" "$PARTICLE_CACHE_DIR"; do if [[ ! -d "$dir" ]]; then echo "ERROR: Required directory does not exist: $dir" >&2 errors=$((errors + 1)) fi done # Check required scripts for script in "$COMPOSEFS_SCRIPT" "$BOOTUPD_SCRIPT" "$APT_LAYER_SCRIPT"; do if [[ ! -f "$script" ]]; then echo "WARNING: Script not found: $script" >&2 elif [[ ! -x "$script" ]]; then echo "WARNING: Script not executable: $script" >&2 fi done # Validate log level case "$PARTICLE_LOG_LEVEL" in DEBUG|INFO|WARNING|ERROR) ;; *) echo "ERROR: Invalid log level: $PARTICLE_LOG_LEVEL" >&2 errors=$((errors + 1)) ;; esac # Validate compression case "$PARTICLE_SQUASHFS_COMPRESSION" in gzip|lzo|xz|zstd) ;; *) echo "ERROR: Invalid compression: $PARTICLE_SQUASHFS_COMPRESSION" >&2 errors=$((errors + 1)) ;; esac # Validate container runtime if [[ -n "$PARTICLE_CONTAINER_RUNTIME" ]]; then if ! command -v "$PARTICLE_CONTAINER_RUNTIME" >/dev/null 2>&1; then echo "WARNING: Container runtime not found: $PARTICLE_CONTAINER_RUNTIME" >&2 fi fi if [[ $errors -gt 0 ]]; then return 1 fi return 0 } # ============================================================================= # INITIALIZATION FUNCTIONS # ============================================================================= # Initialize Particle-OS environment init_particle_environment() { # Create required directories mkdir -p "$PARTICLE_ROOT" "$PARTICLE_CONFIG_DIR" "$PARTICLE_LOG_DIR" "$PARTICLE_CACHE_DIR" mkdir -p "$PARTICLE_BUILD_DIR" "$PARTICLE_WORKSPACE_DIR" "$PARTICLE_TEMP_DIR" mkdir -p "$PARTICLE_LIVE_OVERLAY_DIR" "$PARTICLE_LIVE_UPPER_DIR" "$PARTICLE_LIVE_WORK_DIR" mkdir -p "$PARTICLE_TRANSACTION_BACKUP_DIR" mkdir -p "$PARTICLE_APT_CACHE_DIR" "$PARTICLE_CONTAINER_CACHE_DIR" # Set proper permissions chmod 755 "$PARTICLE_ROOT" "$PARTICLE_CONFIG_DIR" "$PARTICLE_LOG_DIR" "$PARTICLE_CACHE_DIR" chmod 700 "$PARTICLE_TRANSACTION_BACKUP_DIR" # Initialize log files if they don't exist for log_file in "$PARTICLE_MAIN_LOG" "$COMPOSEFS_LOG" "$BOOTUPD_LOG" "$APT_LAYER_LOG"; do if [[ ! -f "$log_file" ]]; then touch "$log_file" chmod 644 "$log_file" fi done # Validate configuration if ! validate_particle_config; then echo "WARNING: Configuration validation failed" >&2 fi } # ============================================================================= # LOGGING FUNCTIONS # ============================================================================= # Log levels PARTICLE_LOG_DEBUG=0 PARTICLE_LOG_INFO=1 PARTICLE_LOG_WARNING=2 PARTICLE_LOG_ERROR=3 # Get numeric log level get_log_level() { case "$PARTICLE_LOG_LEVEL" in DEBUG) echo $PARTICLE_LOG_DEBUG ;; INFO) echo $PARTICLE_LOG_INFO ;; WARNING) echo $PARTICLE_LOG_WARNING ;; ERROR) echo $PARTICLE_LOG_ERROR ;; *) echo $PARTICLE_LOG_INFO ;; esac } # Check if should log at given level should_log() { local level="$1" local current_level current_level=$(get_log_level) case "$level" in DEBUG) [[ $current_level -le $PARTICLE_LOG_DEBUG ]] ;; INFO) [[ $current_level -le $PARTICLE_LOG_INFO ]] ;; WARNING) [[ $current_level -le $PARTICLE_LOG_WARNING ]] ;; ERROR) [[ $current_level -le $PARTICLE_LOG_ERROR ]] ;; *) false ;; esac } # Unified logging function particle_log() { local level="$1" local message="$2" local script_name="${3:-$(basename "${BASH_SOURCE[1]:-unknown}")}" local timestamp timestamp=$(date '+%Y-%m-%d %H:%M:%S') if should_log "$level"; then echo "[$timestamp] [$level] [$script_name] $message" | tee -a "$PARTICLE_MAIN_LOG" fi } # Convenience logging functions log_debug() { particle_log "DEBUG" "$1" "$2"; } log_info() { particle_log "INFO" "$1" "$2"; } log_warning() { particle_log "WARNING" "$1" "$2"; } log_error() { particle_log "ERROR" "$1" "$2"; } # ============================================================================= # UTILITY FUNCTIONS # ============================================================================= # Get Ubuntu version get_ubuntu_version() { lsb_release -rs 2>/dev/null || echo "unknown" } # Get Ubuntu codename get_ubuntu_codename() { lsb_release -cs 2>/dev/null || echo "unknown" } # Check if running as root check_root() { if [[ $EUID -ne 0 ]]; then log_error "This operation requires root privileges" "config" return 1 fi return 0 } # Get system architecture get_architecture() { uname -m } # Check if system supports Secure Boot check_secure_boot() { if [[ -d "/sys/firmware/efi" ]] && [[ -f "/sys/kernel/security/efi_test" ]]; then return 0 else return 1 fi } # ============================================================================= # EXPORT CONFIGURATION # ============================================================================= # Export all configuration variables export PARTICLE_ROOT PARTICLE_CONFIG_DIR PARTICLE_LOG_DIR PARTICLE_CACHE_DIR export PARTICLE_SCRIPTS_DIR COMPOSEFS_SCRIPT BOOTUPD_SCRIPT APT_LAYER_SCRIPT export COMPOSEFS_DIR COMPOSEFS_IMAGES_DIR COMPOSEFS_LAYERS_DIR COMPOSEFS_MOUNTS_DIR export PARTICLE_BUILD_DIR PARTICLE_WORKSPACE_DIR PARTICLE_TEMP_DIR export PARTICLE_LIVE_OVERLAY_DIR PARTICLE_LIVE_UPPER_DIR PARTICLE_LIVE_WORK_DIR export PARTICLE_TRANSACTION_LOG PARTICLE_TRANSACTION_STATE PARTICLE_TRANSACTION_BACKUP_DIR export PARTICLE_LOG_LEVEL PARTICLE_MAIN_LOG COMPOSEFS_LOG BOOTUPD_LOG APT_LAYER_LOG export PARTICLE_LOG_MAX_SIZE PARTICLE_LOG_MAX_FILES PARTICLE_LOG_COMPRESSION PARTICLE_LOG_FILES_PATTERN export PARTICLE_SIGNING_KEY PARTICLE_SIGNING_KEYRING export PARTICLE_SECURE_BOOT_ENABLED PARTICLE_SB_KEYS_DIR export PARTICLE_PARALLEL_JOBS PARTICLE_MAX_PARALLEL_JOBS export PARTICLE_SQUASHFS_COMPRESSION PARTICLE_SQUASHFS_BLOCK_SIZE export PARTICLE_APT_CACHE_DIR PARTICLE_CONTAINER_CACHE_DIR export PARTICLE_CONTAINER_RUNTIME export PARTICLE_REGISTRY_URL PARTICLE_REGISTRY_USERNAME PARTICLE_REGISTRY_PASSWORD export PARTICLE_HTTP_PROXY PARTICLE_HTTPS_PROXY PARTICLE_NO_PROXY # Export functions export -f validate_particle_config init_particle_environment export -f get_log_level should_log particle_log export -f log_debug log_info log_warning log_error export -f get_ubuntu_version get_ubuntu_codename check_root get_architecture check_secure_boot # ============================================================================= # AUTO-INITIALIZATION # ============================================================================= # Auto-initialize if this file is sourced if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then # This file is being executed directly echo "Particle-OS Configuration" echo "=========================" echo "Root directory: $PARTICLE_ROOT" echo "Config directory: $PARTICLE_CONFIG_DIR" echo "Log directory: $PARTICLE_LOG_DIR" echo "Log level: $PARTICLE_LOG_LEVEL" echo "" if init_particle_environment; then echo "Environment initialized successfully" else echo "Environment initialization failed" exit 1 fi else # This file is being sourced init_particle_environment fi