|
#!/bin/bash |
|
|
|
############################################################################### |
|
# Script: Debian 12 (Bookworm) to Debian 13 (Trixie) Upgrade |
|
# Description: Safe automatic upgrade from Debian 12 to Debian 13 |
|
# Author: Auto-generated |
|
# Date: $(date +%Y-%m-%d) |
|
############################################################################### |
|
|
|
set -euo pipefail # Exit on error, undefined vars, pipe failures |
|
|
|
# Colors for output |
|
RED='\033[0;31m' |
|
GREEN='\033[0;32m' |
|
YELLOW='\033[1;33m' |
|
BLUE='\033[0;34m' |
|
NC='\033[0m' # No Color |
|
|
|
# Logging |
|
LOG_FILE="/var/log/debian-upgrade-$(date +%Y%m%d-%H%M%S).log" |
|
exec 1> >(tee -a "$LOG_FILE") |
|
exec 2> >(tee -a "$LOG_FILE" >&2) |
|
|
|
# Functions |
|
log_info() { |
|
echo -e "${BLUE}[INFO]${NC} $1" |
|
} |
|
|
|
log_success() { |
|
echo -e "${GREEN}[SUCCESS]${NC} $1" |
|
} |
|
|
|
log_warning() { |
|
echo -e "${YELLOW}[WARNING]${NC} $1" |
|
} |
|
|
|
log_error() { |
|
echo -e "${RED}[ERROR]${NC} $1" |
|
} |
|
|
|
# Check if script is run as root |
|
check_root() { |
|
if [[ $EUID -ne 0 ]]; then |
|
log_error "This script must be run as root (use sudo)" |
|
exit 1 |
|
fi |
|
log_success "Root check passed" |
|
} |
|
|
|
# Check current Debian version |
|
check_debian_version() { |
|
if [[ ! -f /etc/debian_version ]]; then |
|
log_error "This is not a Debian system" |
|
exit 1 |
|
fi |
|
|
|
DEBIAN_VERSION=$(cat /etc/debian_version) |
|
log_info "Current Debian version: $DEBIAN_VERSION" |
|
|
|
if [[ ! -f /etc/os-release ]]; then |
|
log_error "Cannot read /etc/os-release" |
|
exit 1 |
|
fi |
|
|
|
source /etc/os-release |
|
if [[ "$VERSION_CODENAME" != "bookworm" ]]; then |
|
log_error "This script is only for Debian 12 (Bookworm). Current version: $VERSION_CODENAME" |
|
exit 1 |
|
fi |
|
|
|
log_success "Debian 12 (Bookworm) detected" |
|
} |
|
|
|
# Check disk space |
|
check_disk_space() { |
|
log_info "Checking disk space..." |
|
AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') |
|
|
|
if [[ $AVAILABLE_SPACE -lt 5 ]]; then |
|
log_error "Insufficient disk space. Minimum 5GB required, available: ${AVAILABLE_SPACE}GB" |
|
exit 1 |
|
fi |
|
|
|
log_success "Sufficient disk space available: ${AVAILABLE_SPACE}GB" |
|
} |
|
|
|
# Create backup of important files |
|
backup_important_files() { |
|
log_info "Creating backup of important configuration files..." |
|
|
|
BACKUP_DIR="/root/debian-upgrade-backup-$(date +%Y%m%d-%H%M%S)" |
|
mkdir -p "$BACKUP_DIR" |
|
|
|
# Backup sources.list |
|
if [[ -f /etc/apt/sources.list ]]; then |
|
cp /etc/apt/sources.list "$BACKUP_DIR/sources.list.backup" |
|
fi |
|
|
|
# Backup sources.list.d directory |
|
if [[ -d /etc/apt/sources.list.d ]]; then |
|
cp -r /etc/apt/sources.list.d "$BACKUP_DIR/" |
|
fi |
|
|
|
# Backup important configurations |
|
IMPORTANT_FILES=( |
|
"/etc/fstab" |
|
"/etc/network/interfaces" |
|
"/etc/hosts" |
|
"/etc/hostname" |
|
) |
|
|
|
for file in "${IMPORTANT_FILES[@]}"; do |
|
if [[ -f "$file" ]]; then |
|
cp "$file" "$BACKUP_DIR/" |
|
fi |
|
done |
|
|
|
log_success "Backup created in: $BACKUP_DIR" |
|
echo "$BACKUP_DIR" > /tmp/debian-upgrade-backup-location.txt |
|
} |
|
|
|
# Update current system |
|
update_current_system() { |
|
log_info "Updating current system..." |
|
|
|
apt-get update |
|
apt-get upgrade -y |
|
apt-get dist-upgrade -y |
|
|
|
log_success "Current system updated" |
|
} |
|
|
|
# Clean up unnecessary packages |
|
cleanup_packages() { |
|
log_info "Cleaning up unnecessary packages..." |
|
|
|
apt-get autoremove -y |
|
apt-get autoclean |
|
apt-get clean |
|
|
|
log_success "System cleaned up" |
|
} |
|
|
|
# Update sources.list to Debian 13 (Trixie) |
|
update_sources_list() { |
|
log_info "Updating sources.list to Debian 13 (Trixie)..." |
|
|
|
# Backup original sources.list |
|
cp /etc/apt/sources.list /etc/apt/sources.list.backup.$(date +%Y%m%d) |
|
|
|
# Replace bookworm with trixie in sources.list |
|
sed -i 's/bookworm/trixie/g' /etc/apt/sources.list |
|
|
|
# Also update sources.list.d files |
|
if [[ -d /etc/apt/sources.list.d ]]; then |
|
find /etc/apt/sources.list.d -type f -name "*.list" -exec sed -i 's/bookworm/trixie/g' {} \; |
|
fi |
|
|
|
log_success "Sources.list updated to Debian 13 (Trixie)" |
|
} |
|
|
|
# Minimal upgrade (recommended Debian upgrade method) |
|
minimal_upgrade() { |
|
log_info "Performing minimal upgrade..." |
|
|
|
apt-get update |
|
|
|
# Minimal upgrade as recommended by Debian |
|
apt-get upgrade --without-new-packages -y || true |
|
apt-get full-upgrade -y |
|
|
|
log_success "Minimal upgrade completed" |
|
} |
|
|
|
# Full upgrade |
|
full_upgrade() { |
|
log_info "Performing full upgrade..." |
|
|
|
apt-get update |
|
apt-get full-upgrade -y |
|
|
|
log_success "Full upgrade completed" |
|
} |
|
|
|
# Handle configuration file changes |
|
handle_config_changes() { |
|
log_info "Processing configuration file changes..." |
|
|
|
# Use 'yes' for default options, but ask for confirmation for important changes |
|
# This can be interactive, so we use DEBIAN_FRONTEND=noninteractive |
|
export DEBIAN_FRONTEND=noninteractive |
|
|
|
# For important configurations, use the old version as default |
|
# This prevents important configurations from being overwritten |
|
apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" full-upgrade -y || true |
|
|
|
log_success "Configuration file changes processed" |
|
} |
|
|
|
# Final cleanup |
|
final_cleanup() { |
|
log_info "Performing final cleanup..." |
|
|
|
apt-get autoremove -y |
|
apt-get autoclean |
|
apt-get clean |
|
|
|
log_success "Final cleanup completed" |
|
} |
|
|
|
# Verify upgrade |
|
verify_upgrade() { |
|
log_info "Verifying upgrade..." |
|
|
|
if [[ -f /etc/os-release ]]; then |
|
source /etc/os-release |
|
if [[ "$VERSION_CODENAME" == "trixie" ]]; then |
|
log_success "Upgrade successful! Current version: Debian 13 (Trixie)" |
|
return 0 |
|
else |
|
log_warning "Version check: $VERSION_CODENAME (expected: trixie)" |
|
return 1 |
|
fi |
|
else |
|
log_error "Cannot read /etc/os-release" |
|
return 1 |
|
fi |
|
} |
|
|
|
# Main function |
|
main() { |
|
log_info "=========================================" |
|
log_info "Debian 12 to Debian 13 Upgrade Script" |
|
log_info "=========================================" |
|
log_info "Log file: $LOG_FILE" |
|
echo "" |
|
|
|
# Pre-upgrade checks |
|
check_root |
|
check_debian_version |
|
check_disk_space |
|
|
|
# Ask for confirmation |
|
echo "" |
|
log_warning "WARNING: This script will upgrade your system from Debian 12 to Debian 13" |
|
log_warning "Make sure you have a backup before proceeding!" |
|
echo "" |
|
read -p "Do you want to continue with the upgrade? (yes/no): " -r |
|
echo "" |
|
|
|
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then |
|
log_info "Upgrade cancelled by user" |
|
exit 0 |
|
fi |
|
|
|
# Pre-upgrade steps |
|
backup_important_files |
|
update_current_system |
|
cleanup_packages |
|
|
|
# Upgrade steps |
|
update_sources_list |
|
minimal_upgrade |
|
handle_config_changes |
|
full_upgrade |
|
|
|
# Post-upgrade steps |
|
final_cleanup |
|
verify_upgrade |
|
|
|
echo "" |
|
log_success "=========================================" |
|
log_success "Upgrade process completed!" |
|
log_success "=========================================" |
|
echo "" |
|
log_warning "IMPORTANT: Reboot your system to complete the upgrade:" |
|
log_info " sudo reboot" |
|
echo "" |
|
log_info "Backup location: $(cat /tmp/debian-upgrade-backup-location.txt 2>/dev/null || echo 'Unknown')" |
|
log_info "Log file: $LOG_FILE" |
|
echo "" |
|
} |
|
|
|
# Execute script |
|
main "$@" |