particle-os-tools/install-ubuntu-particle.sh
robojerk 74c7bede5f Initial commit: Particle-OS tools repository
- Complete Particle-OS rebranding from uBlue-OS
- Professional installation system with standardized paths
- Self-initialization system with --init and --reset commands
- Enhanced error messages and dependency checking
- Comprehensive testing infrastructure
- All source scriptlets updated with runtime improvements
- Clean codebase with redundant files moved to archive
- Complete documentation suite
2025-07-11 21:14:33 -07:00

537 lines
No EOL
13 KiB
Bash

#!/bin/bash
# Ubuntu uBlue Installation Script
# Installs and configures the complete Ubuntu uBlue system
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m'
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_step() {
echo -e "${PURPLE}[STEP]${NC} $1"
}
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="/usr/local"
CONFIG_DIR="/usr/local/etc/ubuntu-ublue"
BIN_DIR="/usr/local/bin"
LOG_DIR="/var/log/ubuntu-ublue"
ROOT_DIR="/var/lib/ubuntu-ublue"
# Check if running as root
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
log_info "Please run: sudo $0"
exit 1
fi
}
# Check Ubuntu version
check_ubuntu_version() {
log_step "Checking Ubuntu version..."
if ! command -v lsb_release >/dev/null 2>&1; then
log_error "lsb_release not found. This script requires Ubuntu."
exit 1
fi
local version
version=$(lsb_release -rs)
local codename
codename=$(lsb_release -cs)
log_info "Detected Ubuntu $version ($codename)"
# Check if version is supported (20.04 or later)
if [[ "$version" < "20.04" ]]; then
log_error "Ubuntu $version is not supported. Please use Ubuntu 20.04 or later."
exit 1
fi
log_success "Ubuntu version check passed"
}
# Install system dependencies
install_dependencies() {
log_step "Installing system dependencies..."
# Update package lists
log_info "Updating package lists..."
apt-get update
# Install required packages
local packages=(
"squashfs-tools"
"overlayroot"
"chroot"
"rsync"
"tar"
"gzip"
"xz-utils"
"zstd"
"curl"
"wget"
"gnupg"
"lsb-release"
"util-linux"
"mount"
"umount"
"findmnt"
"lsof"
)
log_info "Installing packages: ${packages[*]}"
apt-get install -y "${packages[@]}"
# Install optional container runtime (podman preferred, fallback to docker)
if command -v podman >/dev/null 2>&1; then
log_info "Podman already installed"
elif command -v docker >/dev/null 2>&1; then
log_info "Docker found, will use as container runtime"
else
log_info "Installing Podman as container runtime..."
apt-get install -y podman
fi
log_success "System dependencies installed"
}
# Create directory structure
create_directories() {
log_step "Creating directory structure..."
local directories=(
"$ROOT_DIR"
"$CONFIG_DIR"
"$LOG_DIR"
"/var/cache/ubuntu-ublue"
"$ROOT_DIR/build"
"$ROOT_DIR/workspace"
"$ROOT_DIR/temp"
"$ROOT_DIR/live-overlay"
"$ROOT_DIR/live-overlay/upper"
"$ROOT_DIR/live-overlay/work"
"$ROOT_DIR/backups"
"/var/lib/composefs-alternative"
"/var/lib/composefs-alternative/images"
"/var/lib/composefs-alternative/layers"
"/var/lib/composefs-alternative/mounts"
)
for dir in "${directories[@]}"; do
log_info "Creating directory: $dir"
mkdir -p "$dir"
done
# Set proper permissions
chmod 755 "$ROOT_DIR" "$CONFIG_DIR" "$LOG_DIR" "/var/cache/ubuntu-ublue"
chmod 700 "$ROOT_DIR/backups"
log_success "Directory structure created"
}
# Install scripts
install_scripts() {
log_step "Installing Ubuntu uBlue scripts..."
# Copy scripts to /usr/local/bin
local scripts=(
"apt-layer.sh"
"bootloader-integration.sh"
"oci-integration.sh"
"test-integration.sh"
"ublue-logrotate.sh"
)
for script in "${scripts[@]}"; do
local source_path="$SCRIPT_DIR/$script"
local target_path="$BIN_DIR/$script"
if [[ -f "$source_path" ]]; then
log_info "Installing $script..."
cp "$source_path" "$target_path"
chmod +x "$target_path"
log_success "Installed $script"
else
log_warning "Script not found: $source_path"
fi
done
# Install configuration file
if [[ -f "$SCRIPT_DIR/ublue-config.sh" ]]; then
log_info "Installing configuration file..."
cp "$SCRIPT_DIR/ublue-config.sh" "$CONFIG_DIR/ublue-config.sh"
chmod 644 "$CONFIG_DIR/ublue-config.sh"
log_success "Configuration file installed"
else
log_warning "Configuration file not found: $SCRIPT_DIR/ublue-config.sh"
fi
log_success "Scripts installed"
}
# Create systemd services
create_systemd_services() {
log_step "Creating systemd services..."
# Create service directory
mkdir -p /etc/systemd/system
# Ubuntu uBlue transaction cleanup service
cat > /etc/systemd/system/ubuntu-ublue-cleanup.service << 'EOF'
[Unit]
Description=Ubuntu uBlue Transaction Cleanup
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/apt-layer.sh --cleanup-incomplete
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
# Ubuntu uBlue log rotation service
cat > /etc/systemd/system/ubuntu-ublue-logrotate.service << 'EOF'
[Unit]
Description=Ubuntu uBlue Log Rotation
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.d/ubuntu-ublue
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
# Enable services
systemctl daemon-reload
systemctl enable ubuntu-ublue-cleanup.service
systemctl enable ubuntu-ublue-logrotate.service
log_success "Systemd services created"
}
# Create logrotate configuration
create_logrotate_config() {
log_step "Creating logrotate configuration..."
cat > /etc/logrotate.d/ubuntu-ublue << 'EOF'
/var/log/ubuntu-ublue/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 644 root root
postrotate
systemctl reload ubuntu-ublue-logrotate.service
endscript
}
EOF
log_success "Logrotate configuration created"
}
# Create man pages
create_man_pages() {
log_step "Creating man pages..."
mkdir -p /usr/local/share/man/man1
# apt-layer man page
cat > /usr/local/share/man/man1/apt-layer.1 << 'EOF'
.TH APT-LAYER 1 "December 2024" "Ubuntu uBlue" "User Commands"
.SH NAME
apt-layer \- Ubuntu uBlue layer management tool
.SH SYNOPSIS
.B apt-layer
[\fIOPTIONS\fR] \fIBASE_IMAGE\fR \fINEW_IMAGE\fR [\fIPACKAGES\fR...]
.SH DESCRIPTION
apt-layer is a tool for managing layers on Ubuntu uBlue systems using ComposeFS.
It provides functionality similar to rpm-ostree for Fedora Silverblue/Kinoite.
.SH OPTIONS
.TP
.B \-\-help
Show help message
.TP
.B \-\-list
List all available ComposeFS images/layers
.TP
.B \-\-info \fIIMAGE\fR
Show information about a specific image
.TP
.B \-\-live-install \fIPACKAGES\fR...
Install packages on live system with overlayfs
.TP
.B \-\-live-commit [\fIMESSAGE\fR]
Commit current live overlay changes as new layer
.TP
.B \-\-live-rollback
Rollback live overlay changes
.TP
.B \-\-container
Use container isolation for package installation
.TP
.B \-\-oci-export \fIIMAGE\fR \fIOCI_NAME\fR
Export ComposeFS image as OCI image
.TP
.B \-\-oci-import \fIOCI_NAME\fR \fITARGET_IMAGE\fR
Import OCI image as ComposeFS image
.SH EXAMPLES
.TP
Create a new layer:
.B apt-layer ubuntu-ublue/base/24.04 ubuntu-ublue/gaming/24.04 steam wine
.TP
Install packages on live system:
.B apt-layer \-\-live-install steam wine
.TP
Commit live changes:
.B apt-layer \-\-live-commit "Add gaming packages"
.SH FILES
.TP
.I /var/lib/ubuntu-ublue/
Ubuntu uBlue root directory
.TP
.I /usr/local/etc/ublue-config.sh
Configuration file
.TP
.I /var/log/ubuntu-ublue/
Log files
.SH SEE ALSO
.BR bootloader-integration (1),
.BR oci-integration (1)
.SH AUTHOR
Ubuntu uBlue Project
EOF
# Update man database
mandb -q
log_success "Man pages created"
}
# Create completion scripts
create_completion_scripts() {
log_step "Creating completion scripts..."
mkdir -p /usr/local/share/bash-completion/completions
# apt-layer completion
cat > /usr/local/share/bash-completion/completions/apt-layer << 'EOF'
_apt_layer() {
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--help --list --info --live-install --live-commit --live-rollback --container --oci-export --oci-import"
case "${prev}" in
--info|--rollback)
# Complete with available images
local images
images=$(apt-layer --list 2>/dev/null | grep -v "Listing" | awk '{print $1}' | tr '\n' ' ')
COMPREPLY=( $(compgen -W "${images}" -- "${cur}") )
return 0
;;
--live-install)
# Complete with common packages
local packages="steam wine firefox chromium-browser vlc"
COMPREPLY=( $(compgen -W "${packages}" -- "${cur}") )
return 0
;;
esac
if [[ ${cur} == * ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
}
complete -F _apt_layer apt-layer
EOF
log_success "Completion scripts created"
}
# Configure environment
configure_environment() {
log_step "Configuring environment..."
# Add to PATH if not already present
if ! grep -q "/usr/local/bin" /etc/environment; then
echo 'PATH="/usr/local/bin:$PATH"' >> /etc/environment
fi
# Create profile script
cat > /etc/profile.d/ubuntu-ublue.sh << 'EOF'
# Ubuntu uBlue environment configuration
export UBLUE_ROOT="/var/lib/ubuntu-ublue"
export UBLUE_CONFIG_DIR="/usr/local/etc/ubuntu-ublue"
# Source configuration if available
if [[ -f "$UBLUE_CONFIG_DIR/ublue-config.sh" ]]; then
source "$UBLUE_CONFIG_DIR/ublue-config.sh"
fi
EOF
chmod +x /etc/profile.d/ubuntu-ublue.sh
log_success "Environment configured"
}
# Run post-installation tests
run_tests() {
log_step "Running post-installation tests..."
if [[ -f "$BIN_DIR/test-integration.sh" ]]; then
log_info "Running integration tests..."
if "$BIN_DIR/test-integration.sh"; then
log_success "All tests passed"
else
log_warning "Some tests failed - check logs for details"
fi
else
log_warning "Test script not found - skipping tests"
fi
}
# Show installation summary
show_summary() {
log_step "Installation Summary"
echo
echo "Ubuntu uBlue has been successfully installed!"
echo
echo "Installed Components:"
echo " • apt-layer.sh - Main layer management tool"
echo " • bootloader-integration.sh - Boot entry management"
echo " • oci-integration.sh - OCI container integration"
echo " • test-integration.sh - Integration testing"
echo " • ublue-config.sh - Unified configuration"
echo
echo "Directories:"
echo " • Root: $ROOT_DIR"
echo " • Config: $CONFIG_DIR"
echo " • Logs: $LOG_DIR"
echo " • Scripts: $BIN_DIR"
echo
echo "Next Steps:"
echo " 1. Create a base image: apt-layer --oci-import ubuntu:24.04 ubuntu-ublue/base/24.04"
echo " 2. Create a layer: apt-layer ubuntu-ublue/base/24.04 ubuntu-ublue/desktop/24.04 gnome-shell"
echo " 3. Install packages live: apt-layer --live-install steam"
echo " 4. View help: apt-layer --help"
echo
echo "Documentation:"
echo " • Man pages: man apt-layer"
echo " • Logs: tail -f $LOG_DIR/ublue.log"
echo " • Tests: $BIN_DIR/test-integration.sh"
echo
log_success "Installation completed successfully!"
}
# Main installation function
main() {
echo "Ubuntu uBlue Installation Script"
echo "================================"
echo
# Check prerequisites
check_root
check_ubuntu_version
# Install components
install_dependencies
create_directories
install_scripts
create_systemd_services
create_logrotate_config
create_man_pages
create_completion_scripts
configure_environment
# Run tests
run_tests
# Show summary
show_summary
}
# Handle command line arguments
case "${1:-}" in
"help"|"-h"|"--help")
cat << EOF
Ubuntu uBlue Installation Script
Usage: $0 [options]
Options:
help, -h, --help Show this help message
Examples:
sudo $0 Install Ubuntu uBlue system
sudo $0 help Show this help message
This script installs and configures the complete Ubuntu uBlue system,
including all scripts, services, and configuration files.
EOF
exit 0
;;
"")
main
;;
*)
log_error "Unknown option: $1"
echo "Use '$0 help' for usage information"
exit 1
;;
esac