Upgrading Ubuntu LTS to a New Version
Upgrading Ubuntu Long Term Support (LTS) releases is a critical maintenance task for system administrators managing production servers. While Ubuntu's upgrade process is generally reliable, performing a major version upgrade requires careful planning, thorough testing, and systematic execution to avoid downtime, data loss, or system instability.
This comprehensive guide walks you through the complete process of upgrading Ubuntu LTS to a new version, from pre-upgrade planning and backup procedures to the actual upgrade execution and post-upgrade verification. Whether you're upgrading from Ubuntu 20.04 to 22.04, or planning for future LTS transitions, this guide provides the knowledge and procedures needed for a successful upgrade.
Table of Contents
- Introduction
- Understanding Ubuntu LTS Release Cycle
- Pre-Upgrade Planning and Assessment
- Backup Strategies and Disaster Recovery
- Testing the Upgrade Process
- Preparing the System for Upgrade
- Performing the Upgrade (Method 1: do-release-upgrade)
- Alternative Upgrade Methods
- Troubleshooting Common Issues
- Post-Upgrade Verification and Cleanup
- Rolling Back Failed Upgrades
- Best Practices for Production Systems
- Automating Upgrades at Scale
- Conclusion
Introduction
Ubuntu LTS (Long Term Support) releases receive five years of standard support and an additional five years of extended security maintenance through Ubuntu Pro. Major LTS versions are released biennially in April, with recent releases including:
- Ubuntu 20.04 LTS (Focal Fossa) - April 2020
- Ubuntu 22.04 LTS (Jammy Jellyfish) - April 2022
- Ubuntu 24.04 LTS (Noble Numbat) - April 2024
Upgrading between LTS releases brings security improvements, kernel updates, newer software versions, and performance enhancements. However, the upgrade process also introduces risks including:
- Application compatibility issues with newer library versions
- Configuration file conflicts requiring manual resolution
- Kernel changes affecting custom drivers or modules
- Third-party repository conflicts
- Service disruption during the upgrade process
A methodical approach to LTS upgrades minimizes these risks while maximizing the benefits of newer Ubuntu versions. This guide emphasizes preparation, testing, and verification to ensure successful upgrades in production environments.
Understanding Ubuntu LTS Release Cycle
Before planning your upgrade, understand Ubuntu's release and support structure.
LTS Support Timeline
# Check current Ubuntu version
lsb_release -a
# Example output:
# Distributor ID: Ubuntu
# Description: Ubuntu 22.04.3 LTS
# Release: 22.04
# Codename: jammy
Ubuntu LTS Support Periods:
| Version | Codename | Release | End of Standard Support | End of ESM |
|---|---|---|---|---|
| 20.04 LTS | Focal Fossa | April 2020 | April 2025 | April 2030 |
| 22.04 LTS | Jammy Jellyfish | April 2022 | April 2027 | April 2032 |
| 24.04 LTS | Noble Numbat | April 2024 | April 2029 | April 2034 |
LTS to LTS Upgrade Path
Ubuntu officially supports direct upgrades only between consecutive LTS releases:
# Supported upgrade paths:
# 20.04 LTS → 22.04 LTS → 24.04 LTS
# NOT supported (skipping versions):
# 20.04 LTS → 24.04 LTS # Must go through 22.04
Point Release Considerations
Ubuntu enables LTS-to-LTS upgrades after the first point release (X.04.1) of the new LTS version:
# Check if upgrades to next LTS are offered
/usr/lib/ubuntu-release-upgrader/check-new-release-gtk
# LTS upgrades typically available after:
# - 22.04.1 release (approximately July 2022 for 22.04)
# - System administrators can upgrade immediately after .0 release
# - Desktop users see prompts after .1 release
Pre-Upgrade Planning and Assessment
Thorough planning prevents upgrade failures and reduces downtime.
System Inventory and Documentation
#!/bin/bash
# Create comprehensive system inventory
REPORT_DIR="/root/upgrade-prep-$(date +%Y%m%d)"
mkdir -p "$REPORT_DIR"
echo "Creating system inventory for upgrade planning..."
# Current system information
hostnamectl > "$REPORT_DIR/system-info.txt"
lsb_release -a >> "$REPORT_DIR/system-info.txt"
uname -a >> "$REPORT_DIR/kernel-info.txt"
# Hardware information
lscpu > "$REPORT_DIR/cpu-info.txt"
free -h > "$REPORT_DIR/memory-info.txt"
df -h > "$REPORT_DIR/disk-info.txt"
lsblk >> "$REPORT_DIR/disk-info.txt"
# Installed packages
dpkg -l > "$REPORT_DIR/installed-packages.txt"
apt-mark showmanual > "$REPORT_DIR/manually-installed.txt"
# Running services
systemctl list-units --type=service --state=running > "$REPORT_DIR/running-services.txt"
# Network configuration
ip addr show > "$REPORT_DIR/network-config.txt"
ip route show >> "$REPORT_DIR/network-config.txt"
cat /etc/netplan/*.yaml > "$REPORT_DIR/netplan-config.txt" 2>/dev/null
# Kernel modules
lsmod > "$REPORT_DIR/loaded-modules.txt"
# Third-party repositories
grep -r --include '*.list' '^deb ' /etc/apt/ > "$REPORT_DIR/repositories.txt"
# Custom configurations
find /etc -name '*.conf' -type f -exec ls -la {} \; > "$REPORT_DIR/config-files.txt"
echo "Inventory saved to $REPORT_DIR"
Compatibility Assessment
Check Application Compatibility:
# Identify critical applications
systemctl list-units --type=service --state=running | grep -v '@'
# Check each critical service for compatibility
# Example: Check PHP version compatibility
php -v
# Check database versions
mysql --version
psql --version
# Check web server versions
nginx -v
apache2 -v
Research Known Issues:
# Search Ubuntu release notes
# Visit: https://wiki.ubuntu.com/JammyJellyfish/ReleaseNotes
# Check for specific application compatibility
apt-cache policy application-name
# Review changelog for major packages
apt-get changelog package-name | less
Estimate Downtime Window
# Calculate estimated upgrade time based on:
# - Number of packages to upgrade
# - Network bandwidth
# - System resources
# Check number of packages
apt list --upgradable | wc -l
# Estimate download size
apt-get -s dist-upgrade | grep "Need to get"
# Typical upgrade times:
# - Small system (< 500 packages): 30-60 minutes
# - Medium system (500-1000 packages): 1-2 hours
# - Large system (> 1000 packages): 2-4 hours
# Add buffer time for unexpected issues
Create Upgrade Plan Document
cat << 'EOF' > /root/upgrade-plan.md
## Ubuntu LTS Upgrade Plan
### System Information
- Hostname: production-web-01
- Current Version: Ubuntu 20.04.6 LTS
- Target Version: Ubuntu 22.04.3 LTS
- Role: Web Application Server
### Pre-Upgrade Checklist
- [ ] Full system backup completed
- [ ] Application compatibility verified
- [ ] Third-party repositories documented
- [ ] Maintenance window scheduled
- [ ] Rollback procedure documented
- [ ] Team notified
- [ ] Monitoring alerts configured
### Upgrade Window
- Date: 2024-12-15
- Start Time: 02:00 UTC
- Estimated Duration: 2 hours
- Maximum Duration: 4 hours
### Rollback Plan
- Snapshot available: Yes
- Snapshot location: /backup/snapshots/pre-upgrade-20241215
- Rollback tested: Yes
- Rollback duration: 30 minutes
### Critical Services
1. Nginx web server
2. PostgreSQL database
3. Redis cache
4. Application workers (Celery)
### Success Criteria
- [ ] System boots successfully
- [ ] All critical services running
- [ ] Application responds correctly
- [ ] No critical errors in logs
- [ ] Performance metrics acceptable
EOF
Backup Strategies and Disaster Recovery
Never upgrade without comprehensive backups and tested recovery procedures.
Full System Backup
#!/bin/bash
# Comprehensive system backup before upgrade
BACKUP_DIR="/backup/pre-upgrade-$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
echo "Starting full system backup..."
# Backup entire system (excluding virtual filesystems)
sudo tar --exclude=/backup \
--exclude=/proc \
--exclude=/tmp \
--exclude=/mnt \
--exclude=/dev \
--exclude=/sys \
--exclude=/run \
--exclude=/media \
--exclude=/var/cache \
--exclude=/var/tmp \
-czf "$BACKUP_DIR/system-backup.tar.gz" /
echo "System backup completed: $BACKUP_DIR/system-backup.tar.gz"
echo "Backup size: $(du -sh $BACKUP_DIR/system-backup.tar.gz)"
# Backup critical configurations separately
tar -czf "$BACKUP_DIR/etc-backup.tar.gz" /etc
tar -czf "$BACKUP_DIR/home-backup.tar.gz" /home
# Create list of installed packages
dpkg --get-selections > "$BACKUP_DIR/package-selections.txt"
Database Backups
#!/bin/bash
# Backup databases before upgrade
BACKUP_DIR="/backup/databases-$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# MySQL/MariaDB backup
if systemctl is-active --quiet mysql; then
echo "Backing up MySQL databases..."
mysqldump --all-databases --single-transaction --quick --lock-tables=false \
> "$BACKUP_DIR/mysql-all-databases.sql"
gzip "$BACKUP_DIR/mysql-all-databases.sql"
fi
# PostgreSQL backup
if systemctl is-active --quiet postgresql; then
echo "Backing up PostgreSQL databases..."
sudo -u postgres pg_dumpall > "$BACKUP_DIR/postgresql-all-databases.sql"
gzip "$BACKUP_DIR/postgresql-all-databases.sql"
fi
echo "Database backups completed in $BACKUP_DIR"
Snapshot-Based Backups (Virtual Machines)
# For VMware environments
# Take snapshot before upgrade
# Name: "Pre-upgrade to 22.04 - $(date +%Y%m%d)"
# For VirtualBox
VBoxManage snapshot "Ubuntu-Server" take "Pre-Ubuntu-22.04-Upgrade" \
--description "Snapshot before upgrading from 20.04 to 22.04"
# For LVM-based systems
# Create LVM snapshot
sudo lvcreate -L 20G -s -n root-snapshot /dev/vg0/root
# For cloud instances (AWS)
# Create AMI or EBS snapshot
aws ec2 create-image --instance-id i-1234567890abcdef0 \
--name "Pre-upgrade-ubuntu-2204-$(date +%Y%m%d)" \
--description "Backup before Ubuntu 22.04 upgrade"
Verify Backup Integrity
#!/bin/bash
# Verify backup integrity
BACKUP_FILE="/backup/pre-upgrade-20241215/system-backup.tar.gz"
echo "Verifying backup integrity..."
# Test archive integrity
if tar -tzf "$BACKUP_FILE" > /dev/null; then
echo "✓ Backup archive is valid"
else
echo "✗ Backup archive is corrupted!"
exit 1
fi
# Check backup size
SIZE=$(du -sh "$BACKUP_FILE" | cut -f1)
echo "Backup size: $SIZE"
# List backup contents sample
echo "Sample of backup contents:"
tar -tzf "$BACKUP_FILE" | head -20
# Calculate checksum
sha256sum "$BACKUP_FILE" > "$BACKUP_FILE.sha256"
echo "Checksum saved to $BACKUP_FILE.sha256"
Testing the Upgrade Process
Always test the upgrade on a non-production system first.
Create Test Environment
# Option 1: Clone virtual machine
# Create exact copy of production system
# Option 2: Use cloud snapshot
# AWS - Launch instance from snapshot
aws ec2 run-instances --image-id ami-snapshot-id \
--instance-type t3.medium \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=upgrade-test}]'
# Option 3: LXD container clone
lxc copy production-server upgrade-test
lxc start upgrade-test
# Option 4: Local VM with Vagrant
vagrant init ubuntu/focal64
vagrant up
vagrant ssh
Run Test Upgrade
#!/bin/bash
# Test upgrade procedure
echo "Starting test upgrade on non-production system..."
# Update current system
sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt autoremove -y
# Clean package cache
sudo apt clean
# Reboot if kernel updated
if [ -f /var/run/reboot-required ]; then
echo "Reboot required, rebooting test system..."
sudo reboot
# Wait and reconnect
fi
# Perform upgrade
sudo do-release-upgrade -d # -d for development release if testing early
# Document any issues encountered
# Note configuration file conflicts
# Record services that failed to start
Document Test Results
cat << 'EOF' > /root/test-upgrade-results.md
## Test Upgrade Results
### Test Environment
- Date: 2024-12-10
- System: Clone of production-web-01
- From: Ubuntu 20.04.6 LTS
- To: Ubuntu 22.04.3 LTS
### Upgrade Process
- Start time: 14:30
- End time: 16:15
- Duration: 1 hour 45 minutes
- Download size: 1.2 GB
- Packages upgraded: 847
### Issues Encountered
1. **PHP version change (7.4 → 8.1)**
- Action: Updated application code
- Time: 30 minutes
2. **PostgreSQL configuration conflict**
- File: /etc/postgresql/14/main/postgresql.conf
- Action: Kept local version
- Verified: Working correctly
3. **Custom systemd service failed**
- Service: custom-app.service
- Issue: Deprecated directive
- Fix: Updated service file
### Post-Upgrade Status
- ✓ System boots successfully
- ✓ All services started
- ✓ Application functional
- ✓ Database accessible
- ✓ Performance acceptable
### Recommendations
1. Update PHP code before production upgrade
2. Review PostgreSQL configuration changes
3. Update custom systemd services
4. Allocate 2-hour maintenance window
5. Have database administrator on call
EOF
Preparing the System for Upgrade
Proper preparation prevents most upgrade issues.
Update Current System
#!/bin/bash
# Fully update current system before upgrading
echo "Updating current Ubuntu 20.04 system..."
# Update package lists
sudo apt update
# Upgrade all installed packages
sudo apt upgrade -y
# Perform distribution upgrade (within current version)
sudo apt dist-upgrade -y
# Remove unused packages
sudo apt autoremove -y
# Clean package cache
sudo apt autoclean
echo "Current system fully updated"
Resolve Package Issues
# Check for broken packages
sudo dpkg --configure -a
sudo apt --fix-broken install
# Check for held packages
apt-mark showhold
# If packages are held, investigate why
# Release hold if safe
# sudo apt-mark unhold package-name
# Verify no packages in inconsistent state
sudo dpkg --audit
Disable Third-Party Repositories
#!/bin/bash
# Disable third-party repositories before upgrade
echo "Disabling third-party repositories..."
# Backup repository configuration
sudo cp -r /etc/apt/sources.list.d /etc/apt/sources.list.d.backup
# Disable PPA repositories
sudo mv /etc/apt/sources.list.d/ppa-*.list /etc/apt/sources.list.d.backup/
# Alternative: Comment out third-party sources
sudo sed -i 's/^deb /#deb /g' /etc/apt/sources.list.d/*.list
# Keep only official Ubuntu repositories
sudo apt update
echo "Third-party repositories disabled"
echo "Re-enable after upgrade completion"
Remove Obsolete Packages
# Remove old kernels (keep current and one previous)
sudo apt autoremove --purge
# Remove obsolete packages
sudo apt remove --purge $(dpkg -l | grep '^rc' | awk '{print $2}')
# Check for manually installed packages that might conflict
apt list --installed | grep -v "$(lsb_release -cs)"
Free Up Disk Space
#!/bin/bash
# Ensure sufficient disk space for upgrade
echo "Checking available disk space..."
# Check root partition space
ROOT_AVAILABLE=$(df -h / | tail -1 | awk '{print $4}')
echo "Available space on /: $ROOT_AVAILABLE"
# Upgrade requires at least 5GB free on /
if [ $(df / | tail -1 | awk '{print $4}') -lt 5242880 ]; then
echo "WARNING: Less than 5GB free on /"
echo "Cleaning up space..."
# Clean package cache
sudo apt clean
# Remove old log files
sudo journalctl --vacuum-time=7d
# Clean temp files
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*
# Remove old kernels
sudo apt autoremove --purge
fi
# Verify space after cleanup
df -h /
Backup and Update Configuration Files
#!/bin/bash
# Backup configuration files before upgrade
CONFIG_BACKUP="/root/config-backup-$(date +%Y%m%d)"
mkdir -p "$CONFIG_BACKUP"
# Backup critical configurations
sudo cp -r /etc/netplan "$CONFIG_BACKUP/"
sudo cp -r /etc/nginx "$CONFIG_BACKUP/"
sudo cp -r /etc/apache2 "$CONFIG_BACKUP/"
sudo cp -r /etc/mysql "$CONFIG_BACKUP/"
sudo cp -r /etc/postgresql "$CONFIG_BACKUP/"
sudo cp -r /etc/ssh "$CONFIG_BACKUP/"
sudo cp /etc/fstab "$CONFIG_BACKUP/"
sudo cp /etc/hosts "$CONFIG_BACKUP/"
# Create tarball
cd /root
tar -czf config-backup-$(date +%Y%m%d).tar.gz config-backup-$(date +%Y%m%d)/
echo "Configuration backup saved to $CONFIG_BACKUP"
Performing the Upgrade (Method 1: do-release-upgrade)
The official and recommended method for upgrading Ubuntu LTS releases.
Update Release Upgrader Configuration
# Configure to allow LTS to LTS upgrades
sudo nano /etc/update-manager/release-upgrades
# Ensure this line is present:
# Prompt=lts
# This ensures only LTS releases are offered for upgrade
Check for Available Upgrades
# Check if new LTS release is available
sudo do-release-upgrade -c
# Example output:
# Checking for a new Ubuntu release
# New release '22.04.3 LTS' available.
# Run 'do-release-upgrade' to upgrade to it.
Start the Upgrade Process
#!/bin/bash
# Perform the actual upgrade
# Ensure you're in a stable terminal session
# Use screen or tmux for SSH connections to prevent disconnection issues
# Start screen session
screen -S upgrade
# Or start tmux session
# tmux new -s upgrade
# Begin upgrade
sudo do-release-upgrade
# The upgrade tool will:
# 1. Check system readiness
# 2. Calculate required changes
# 3. Download packages
# 4. Install new packages
# 5. Handle configuration file conflicts
# 6. Remove obsolete packages
# 7. Prompt for reboot
Handling Configuration File Conflicts
During the upgrade, you'll encounter configuration file conflicts:
# Typical prompt:
# Configuration file '/etc/nginx/nginx.conf'
# ==> Modified (by you or by a script) since installation.
# ==> Package distributor has shipped an updated version.
# What would you like to do about it?
# Your options are:
# Y or I : install the package maintainer's version
# N or O : keep your currently-installed version
# D : show the differences between the versions
# Z : start a shell to examine the situation
# Best practice: Choose 'D' to see differences
# Then decide based on your customizations
# For files you've heavily modified: Choose 'N' (keep)
# For files you haven't modified: Choose 'Y' (install new)
# You can always merge changes later
Monitor Upgrade Progress
# In another terminal (if available)
# Monitor disk I/O
iostat -x 5
# Monitor network activity
iftop
# Watch syslog
tail -f /var/log/syslog
# Monitor process activity
htop
Complete the Upgrade
# After package installation completes
# Remove obsolete packages when prompted
# Restart when prompted
sudo reboot
# After reboot, verify new version
lsb_release -a
# Output should show:
# Description: Ubuntu 22.04.3 LTS
# Release: 22.04
Alternative Upgrade Methods
While do-release-upgrade is recommended, alternative methods exist.
Manual Upgrade via APT
#!/bin/bash
# Advanced users only - manual upgrade method
# Update sources.list to new release
sudo sed -i 's/focal/jammy/g' /etc/apt/sources.list
# Update package lists
sudo apt update
# Upgrade packages
sudo apt upgrade -y
sudo apt dist-upgrade -y
# Install new Ubuntu base
sudo apt install ubuntu-desktop # or ubuntu-server
# Reboot
sudo reboot
# Note: This method is NOT officially supported
# Use only if do-release-upgrade fails
Upgrade from Installation Media
# If system upgrade fails, boot from Ubuntu 22.04 USB
# Choose "Upgrade Ubuntu 20.04 to 22.04"
# Existing data and configurations preserved
# This method requires:
# - Physical or virtual media access
# - Potential downtime
# - Manual intervention
Troubleshooting Common Issues
Even well-planned upgrades can encounter issues.
Upgrade Fails to Start
# Issue: do-release-upgrade reports no new release
# Solution 1: Check release upgrade configuration
cat /etc/update-manager/release-upgrades
# Ensure: Prompt=lts
# Solution 2: Force check for development release
sudo do-release-upgrade -d
# Solution 3: Update release upgrader
sudo apt update
sudo apt install ubuntu-release-upgrader-core
# Solution 4: Check if you're on latest point release
sudo apt update && sudo apt dist-upgrade
Package Dependency Conflicts
# Issue: Unresolved dependencies during upgrade
# View detailed dependency information
apt-cache depends package-name
apt-cache rdepends package-name
# Try to fix broken packages
sudo apt --fix-broken install
sudo dpkg --configure -a
# Remove conflicting package temporarily
sudo apt remove conflicting-package
# Retry upgrade
sudo do-release-upgrade
SSH Connection Lost During Upgrade
# Prevention: Use screen or tmux
# Start screen before upgrade
screen -S ubuntu-upgrade
# If disconnected, reconnect
screen -r ubuntu-upgrade
# Recovery if upgrade interrupted:
# Reconnect to server (console access may be required)
# Continue interrupted upgrade
sudo dpkg --configure -a
sudo apt --fix-broken install
sudo apt dist-upgrade
Boot Failure After Upgrade
# Access system via recovery mode or rescue disk
# Mount root filesystem
mount /dev/sda1 /mnt # adjust device as needed
# Chroot into system
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt
# Repair GRUB bootloader
update-grub
grub-install /dev/sda
# Fix package issues
dpkg --configure -a
apt --fix-broken install
# Exit chroot and reboot
exit
umount /mnt/dev /mnt/proc /mnt/sys
umount /mnt
reboot
Services Fail to Start
# Check service status
systemctl status service-name
# View service logs
journalctl -u service-name -n 50
# Check for configuration file issues
service-name -t # test configuration (nginx, apache2)
# Restore configuration from backup if needed
sudo cp /root/config-backup-20241215/nginx/nginx.conf /etc/nginx/
# Restart service
sudo systemctl restart service-name
Kernel Panic or System Instability
# Boot into previous kernel from GRUB menu
# Hold Shift during boot to access GRUB
# Select "Advanced options"
# Choose previous kernel version
# After booting into old kernel
# Remove problematic new kernel
sudo apt remove linux-image-5.15.0-*
# Hold kernel version temporarily
sudo apt-mark hold linux-image-generic
# Investigate kernel issues
dmesg | less
journalctl -k
# When resolved, unhold kernel
sudo apt-mark unhold linux-image-generic
Post-Upgrade Verification and Cleanup
Thorough verification ensures the upgrade succeeded completely.
System Verification Checklist
#!/bin/bash
# Comprehensive post-upgrade verification
echo "Post-Upgrade Verification Checklist"
echo "==================================="
# Verify Ubuntu version
echo -n "Ubuntu version: "
lsb_release -rs
# Verify kernel version
echo -n "Kernel version: "
uname -r
# Check system status
echo -n "System degraded: "
systemctl is-system-running
# List failed services
echo "Failed services:"
systemctl list-units --state=failed
# Check disk space
echo "Disk space:"
df -h / | tail -1
# Verify network connectivity
echo -n "Internet connectivity: "
ping -c 1 google.com > /dev/null 2>&1 && echo "OK" || echo "FAILED"
# Check DNS resolution
echo -n "DNS resolution: "
nslookup ubuntu.com > /dev/null 2>&1 && echo "OK" || echo "FAILED"
# List package issues
echo "Package issues:"
dpkg --audit
echo "Verification complete"
Application Testing
#!/bin/bash
# Test critical applications
# Web server
if systemctl is-active --quiet nginx; then
curl -I http://localhost
echo "✓ Nginx responding"
fi
# Database
if systemctl is-active --quiet postgresql; then
sudo -u postgres psql -c "SELECT version();"
echo "✓ PostgreSQL responding"
fi
# Application-specific tests
# Add your application health checks here
curl http://localhost:8000/health
systemctl status custom-app.service
Review Log Files
# Check for errors in system logs
sudo journalctl -p err -b
# Check specific service logs
sudo journalctl -u nginx.service -b
sudo journalctl -u postgresql.service -b
# Check kernel messages
sudo dmesg | grep -i error
# Review auth log
sudo tail -100 /var/log/auth.log
# Check for security issues
sudo grep -i "failure" /var/log/auth.log
Re-enable Third-Party Repositories
#!/bin/bash
# Re-enable third-party repositories for new release
echo "Re-enabling third-party repositories..."
# Update repository release names
# focal → jammy for Ubuntu 22.04
sudo sed -i 's/focal/jammy/g' /etc/apt/sources.list.d/*.list
# Or restore and update from backup
# sudo cp -r /etc/apt/sources.list.d.backup/* /etc/apt/sources.list.d/
# sudo sed -i 's/focal/jammy/g' /etc/apt/sources.list.d/*.list
# Update package lists
sudo apt update
# Fix any repository issues
# Some PPAs may not support new release yet
echo "Third-party repositories updated"
Clean Up Obsolete Packages
# Remove old kernel versions (keep current and one previous)
sudo apt autoremove --purge -y
# Remove obsolete packages
sudo apt autopurge -y
# Clean package cache
sudo apt clean
# Remove configuration files from removed packages
sudo dpkg --purge $(dpkg -l | grep '^rc' | awk '{print $2}')
# Check for residual issues
sudo deborphan # install: sudo apt install deborphan
Update Monitoring and Alerts
# Update monitoring configurations for new OS version
# Update alert thresholds if needed
# Verify monitoring agents still functioning
# Example: Update node_exporter for Prometheus
systemctl status node_exporter
# Example: Update monitoring dashboards
# Update OS version tags in Grafana
# Update alert rules for new kernel version
Rolling Back Failed Upgrades
If the upgrade fails critically, rollback procedures restore the previous state.
Restore from Snapshot (Virtual Machines)
# VMware: Revert to snapshot
# 1. Power off VM
# 2. Right-click VM → Snapshot → Revert to snapshot
# 3. Select pre-upgrade snapshot
# 4. Power on VM
# VirtualBox: Restore snapshot
VBoxManage controlvm "Ubuntu-Server" poweroff
VBoxManage snapshot "Ubuntu-Server" restore "Pre-Ubuntu-22.04-Upgrade"
VBoxManage startvm "Ubuntu-Server" --type headless
# Cloud instance (AWS): Launch from AMI
aws ec2 run-instances --image-id ami-backup-id \
--instance-type t3.medium \
--subnet-id subnet-xxxxx \
--security-group-ids sg-xxxxx
Restore from LVM Snapshot
# Merge LVM snapshot back to original volume
sudo lvconvert --merge /dev/vg0/root-snapshot
# Reboot to complete merge
sudo reboot
# After reboot, snapshot volume is removed
# Original volume restored to pre-upgrade state
Restore from Tar Backup
#!/bin/bash
# Restore from tar backup (last resort)
# Boot from live USB/rescue mode
# Mount root filesystem
mount /dev/sda1 /mnt
# Clear current system
rm -rf /mnt/*
# Restore from backup
cd /mnt
tar -xzf /backup/pre-upgrade-20241215/system-backup.tar.gz
# Reinstall GRUB
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt
grub-install /dev/sda
update-grub
# Exit and reboot
exit
umount /mnt/dev /mnt/proc /mnt/sys
umount /mnt
reboot
Downgrade Specific Packages
# If only specific packages are problematic
# Downgrade to previous version
# List available package versions
apt-cache policy package-name
# Install specific version
sudo apt install package-name=version
# Hold package at current version
sudo apt-mark hold package-name
# Example: Downgrade PHP
sudo apt install php=7.4* -y
sudo apt-mark hold php*
Best Practices for Production Systems
Minimize risk and downtime in production environments.
Staged Rollout Strategy
# 1. Test environment: Week 1
# 2. Development environment: Week 2
# 3. Staging environment: Week 3
# 4. Production (1 server): Week 4
# 5. Production (remaining servers): Week 5-8
# Monitor each stage for issues before proceeding
Blue-Green Deployment
# Maintain parallel infrastructure
# Blue: Current Ubuntu 20.04 servers
# Green: New Ubuntu 22.04 servers
# 1. Deploy application on new 22.04 servers
# 2. Test thoroughly
# 3. Switch traffic to new servers
# 4. Monitor for issues
# 5. Keep old servers for quick rollback
# 6. Decommission old servers after stability confirmed
# Load balancer switch
# Update DNS or load balancer to point to new servers
Automate with Configuration Management
# Ansible playbook for Ubuntu upgrade
---
- name: Upgrade Ubuntu LTS
hosts: ubuntu_servers
serial: 1 # Upgrade one server at a time
tasks:
- name: Update all packages
apt:
update_cache: yes
upgrade: dist
- name: Check if reboot required
stat:
path: /var/run/reboot-required
register: reboot_required
- name: Reboot if necessary
reboot:
reboot_timeout: 300
when: reboot_required.stat.exists
- name: Perform release upgrade
command: do-release-upgrade -f DistUpgradeViewNonInteractive
register: upgrade_result
- name: Reboot after upgrade
reboot:
reboot_timeout: 600
Maintenance Window Planning
# Schedule maintenance window
cat << 'EOF'
Maintenance Window Notification
Service: Production Web Servers
Date: December 15, 2024
Time: 02:00 - 06:00 UTC (4-hour window)
Expected Impact: Service interruption
Expected Duration: 2 hours
Reason: Ubuntu LTS upgrade (20.04 → 22.04)
Rollback Plan: Available within 30 minutes if issues occur
Support Contact: [email protected]
Status Page: https://status.example.com
EOF
Automating Upgrades at Scale
Managing dozens or hundreds of servers requires automation.
Unattended Upgrades
# Configure unattended-upgrades for security updates
sudo apt install unattended-upgrades
# Configure automatic upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
# Edit configuration
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
# Enable automatic reboot if needed
# Unattended-Upgrade::Automatic-Reboot "true";
# Unattended-Upgrade::Automatic-Reboot-Time "03:00";
Landscape (Ubuntu Management Tool)
# Canonical's Landscape for managing multiple Ubuntu systems
# Commercial tool with free tier for limited servers
# Install landscape client
sudo apt install landscape-client
# Configure landscape
sudo landscape-config --account-name ACCOUNT --computer-title "Server01"
# Manage upgrades through web interface
Custom Automation Script
#!/bin/bash
# Automated LTS upgrade script with safety checks
set -e # Exit on error
LOG_FILE="/var/log/ubuntu-upgrade-$(date +%Y%m%d).log"
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Pre-flight checks
log "Starting pre-flight checks..."
# Check internet connectivity
if ! ping -c 1 google.com > /dev/null 2>&1; then
log "ERROR: No internet connectivity"
exit 1
fi
# Check disk space (need at least 5GB free)
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
if [ $FREE_SPACE -lt 5242880 ]; then
log "ERROR: Insufficient disk space"
exit 1
fi
# Create backup
log "Creating backup..."
BACKUP_DIR="/backup/pre-upgrade-$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
tar -czf "$BACKUP_DIR/etc-backup.tar.gz" /etc
dpkg --get-selections > "$BACKUP_DIR/package-selections.txt"
# Update current system
log "Updating current system..."
apt update
apt upgrade -y
apt dist-upgrade -y
# Perform upgrade
log "Starting release upgrade..."
DEBIAN_FRONTEND=noninteractive do-release-upgrade -f DistUpgradeViewNonInteractive
log "Upgrade completed successfully"
# Reboot
log "Rebooting system..."
reboot
Conclusion
Upgrading Ubuntu LTS releases is a manageable process when approached methodically with proper planning, testing, and backup procedures. While Ubuntu's do-release-upgrade tool handles most of the complexity, successful upgrades in production environments require careful preparation and verification.
Key Takeaways:
-
Never Skip Planning: Document your system, identify dependencies, and create detailed upgrade plans before beginning.
-
Always Backup: Comprehensive backups are mandatory. Test restore procedures before the upgrade.
-
Test First: Never upgrade production without testing the exact procedure on a replica system first.
-
Use Official Tools: The do-release-upgrade utility is the supported and most reliable upgrade method.
-
Staged Rollouts: Upgrade production systems incrementally, monitoring each stage before proceeding.
-
Verify Thoroughly: Post-upgrade verification is as important as the upgrade itself. Test all critical services and applications.
-
Have a Rollback Plan: Know your recovery options and practice them before the upgrade window.
-
Monitor and Document: Log everything during the upgrade and document any issues for future reference.
Recommended Timeline for Production Upgrades:
- Month 1: Test upgrade on replica system, document issues
- Month 2: Update procedures, test again, train team
- Month 3: Upgrade non-critical production systems
- Month 4-6: Staged rollout to critical production systems
When to Upgrade:
Ubuntu LTS upgrades should be performed:
- Before current LTS reaches end-of-life
- When applications require newer dependencies
- To access security features in newer releases
- Following thorough testing and validation
When to Delay:
Consider delaying upgrades when:
- Critical applications lack compatibility testing
- Major project deadlines approach
- Team lacks bandwidth for potential issues
- Current LTS still has years of support remaining
By following the procedures outlined in this guide, you can confidently upgrade Ubuntu LTS systems while minimizing risk and downtime. Remember that patience and thoroughness prevent far more problems than they cause.
Next Steps
After a successful upgrade:
- Document lessons learned and update procedures
- Train team members on new features and changes
- Update disaster recovery documentation
- Review and optimize system configurations for new release
- Plan for the next LTS upgrade cycle
- Subscribe to Ubuntu security announcements
- Join Ubuntu community channels for ongoing support
Ubuntu's LTS releases provide a stable, well-supported foundation for production systems. With proper upgrade procedures, you can maintain that stability while benefiting from the security, performance, and feature improvements in newer releases.


