- 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
537 lines
No EOL
13 KiB
Bash
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 |