Ubuntu 22.04 LTS has served as a rock-solid foundation for production VPS workloads since its release in April 2022. But with Ubuntu 24.04 LTS (Noble Numbat) now well into its support lifecycle, the question is no longer whether to upgrade but when. The newer release brings a modern kernel, significantly improved security defaults, updated language runtimes, and performance enhancements across the board. For anyone running a live VPS with production services, the upgrade process requires careful planning, methodical execution, and a solid rollback strategy. This guide walks through every step of migrating a live Ubuntu 22.04 VPS to 24.04 LTS, from initial assessment through post-upgrade verification and troubleshooting.
MassiveGRID Ubuntu VPS includes: Ubuntu 24.04 LTS pre-installed · Proxmox HA cluster with automatic failover · Ceph 3x replicated NVMe storage · Independent CPU/RAM/storage scaling · 12 Tbps DDoS protection · 4 global datacenter locations · 100% uptime SLA · 24/7 human support rated 9.5/10
Deploy a self-managed VPS — from $1.99/mo
Need dedicated resources? — from $19.80/mo
Want fully managed hosting? — we handle everything
When to Upgrade: The 22.04 Timeline and What 24.04 Offers
Ubuntu 22.04 LTS receives standard security maintenance through April 2027, with Extended Security Maintenance (ESM) available through 2032 via Ubuntu Pro. That gives you runway, but running on an older LTS means living with older package versions, missing kernel improvements, and gradually accumulating technical debt as upstream projects drop support for Jammy-era dependencies.
Ubuntu 24.04 LTS brings substantial improvements that matter for VPS workloads. The kernel jumps to 6.8, delivering better io_uring performance, improved eBPF capabilities, and more efficient memory management under pressure. The default security posture is tightened with AppArmor enabled by default for more services, unprivileged user namespaces restricted via AppArmor profiles, and dmesg access restricted for non-root users. On the runtime side, you get Python 3.12, PHP 8.3, Ruby 3.2, Go 1.22, and GCC 14 from the default repositories. Systemd 255 brings improved boot performance and better container integration. Netplan becomes the sole network configuration backend, replacing the lingering ifupdown configurations some servers still carried.
The performance gains alone justify the migration for most workloads. The 6.8 kernel shows measurable improvements in filesystem operations on NVMe storage, network throughput under high connection counts, and memory compaction during allocation pressure. If your VPS runs database workloads, web serving, or containerized applications, you will see tangible benefits.
Critical Decision: In-Place Upgrade vs. Fresh Install and Migrate
Before touching a single package, decide your migration strategy. You have two options, and neither is universally superior.
In-place upgrade using do-release-upgrade transforms your existing 22.04 installation into 24.04 while preserving your data, configurations, installed packages, and user accounts. The advantage is continuity. Everything stays in place, IP addresses remain unchanged, and services resume with their existing data. The risk is that accumulated configuration drift, third-party repositories, custom kernel modules, or unusual package states can cause the upgrade to fail partway through, potentially leaving the system in a broken state.
Fresh install with data migration gives you a clean 24.04 installation on a new VPS, then you migrate data, configurations, and services from the old server. This approach is inherently safer because the old server remains untouched until the new one is validated. The tradeoff is significantly more manual work: reinstalling packages, reconfiguring services, migrating databases, updating DNS, and potentially dealing with IP address changes.
For most production VPS workloads, the in-place upgrade is the practical choice if your server is well-maintained and running standard Ubuntu packages. Choose the fresh install route if your server has been running for years with extensive manual modifications, has third-party kernel modules, or if you can afford the downtime window for a proper migration. Either way, the pre-upgrade checklist below applies to both strategies.
Pre-Upgrade Checklist: Do Not Skip These Steps
The time you invest in preparation directly determines whether your upgrade succeeds cleanly or turns into a midnight emergency. Work through every item on this checklist before beginning the upgrade.
Create a Complete Backup
This is non-negotiable. Before any upgrade, create a full backup of your VPS that you have verified you can restore from. If your hosting provider offers snapshot functionality, take a snapshot immediately before beginning. Additionally, create application-level backups of databases, configuration files, and critical data directories.
For a systematic approach to backup automation, see our guide on automating backups on Ubuntu VPS. At minimum, back up the following:
# Database dumps
mysqldump --all-databases --single-transaction > /backup/all-databases-$(date +%Y%m%d).sql
pg_dumpall > /backup/postgres-all-$(date +%Y%m%d).sql
# Critical configuration directories
tar czf /backup/etc-backup-$(date +%Y%m%d).tar.gz /etc/
tar czf /backup/var-www-$(date +%Y%m%d).tar.gz /var/www/
# List of installed packages for reference
dpkg --get-selections > /backup/package-list-$(date +%Y%m%d).txt
apt list --installed > /backup/apt-installed-$(date +%Y%m%d).txt
# Crontabs
crontab -l > /backup/root-crontab-$(date +%Y%m%d).txt
for user in $(cut -f1 -d: /etc/passwd); do
crontab -u "$user" -l 2>/dev/null > "/backup/${user}-crontab-$(date +%Y%m%d).txt"
done
Document Your Running Services
Before upgrading, record exactly what is running and how it is configured. After the upgrade, this inventory becomes your verification checklist.
# List all active services
systemctl list-units --type=service --state=running > /backup/running-services.txt
# List listening ports and associated processes
ss -tlnp > /backup/listening-ports.txt
# Document enabled services (services that start at boot)
systemctl list-unit-files --state=enabled > /backup/enabled-services.txt
# Record current kernel and key package versions
uname -r > /backup/kernel-version.txt
php -v >> /backup/versions.txt 2>/dev/null
mysql --version >> /backup/versions.txt 2>/dev/null
python3 --version >> /backup/versions.txt 2>/dev/null
nginx -v >> /backup/versions.txt 2>/dev/null
node -v >> /backup/versions.txt 2>/dev/null
Document Modified Configuration Files
During the upgrade, dpkg will ask whether to keep your existing configuration files or replace them with the package maintainer's updated versions. Knowing exactly which files you have modified makes these decisions straightforward.
# Find all configuration files you've modified from package defaults
dpkg-query -W -f='${Conffiles}\n' '*' | grep -v '^\s*$' | while read -r hash file; do
if [ -f "$file" ]; then
current_hash=$(md5sum "$file" | cut -d' ' -f1)
if [ "$current_hash" != "$hash" ]; then
echo "MODIFIED: $file"
fi
fi
done > /backup/modified-conffiles.txt
Review this list carefully. For each modified file, understand what changes you made and why. Common culprits include /etc/nginx/nginx.conf, /etc/mysql/mysql.conf.d/mysqld.cnf, /etc/php/8.1/fpm/php.ini, /etc/ssh/sshd_config, and /etc/sysctl.conf. During the upgrade, you will generally want to keep your version of files you have intentionally customized and accept the maintainer's version for files you have not touched.
Check Application Compatibility
Ubuntu 24.04 ships different default versions of key runtimes. Verify your applications are compatible before upgrading:
PHP: Ubuntu 22.04 ships PHP 8.1; Ubuntu 24.04 ships PHP 8.3. Check your application's composer.json for PHP version constraints. Laravel 10+ and WordPress 6.4+ support PHP 8.3, but older applications or plugins may use deprecated features. Run php -l against your codebase if possible, and check for uses of deprecated functions that were removed in 8.2 or 8.3.
MySQL: Ubuntu 22.04 includes MySQL 8.0; Ubuntu 24.04 defaults to MySQL 8.0 as well (though you may see minor version differences). The transition is usually smooth, but verify your application does not rely on deprecated SQL modes or authentication plugins. If you are using MariaDB from third-party repos, check compatibility separately.
Python: Ubuntu 22.04 ships Python 3.10; Ubuntu 24.04 ships Python 3.12. Python 3.12 removes several long-deprecated modules (distutils, imp, aifc, cgi, and others). If your applications use virtual environments, they will need to be recreated after the upgrade.
Test on a Temporary VPS First
If your production server runs anything beyond a simple website, spin up a temporary MassiveGRID VPS with Ubuntu 22.04, clone your environment, and perform the upgrade there first. This lets you discover any issues without risking production downtime. A test VPS costs a few dollars for a few hours and can save you from a multi-hour production outage.
Restore your backup onto the test VPS, run the upgrade, verify all services come up correctly, and document any issues. Only then proceed with production.
Pre-Upgrade Steps: Preparing the System
Fully Update Ubuntu 22.04
Your system must be completely up to date on 22.04 before attempting the LTS upgrade. The upgrade tool will refuse to proceed if packages are outdated.
apt update && apt upgrade -y && apt dist-upgrade -y
Reboot if a new kernel was installed, then verify you are running the latest kernel:
reboot
# After reboot:
uname -r
Remove Unused Packages
Clean up packages that are no longer needed. Fewer packages means fewer potential conflicts during the upgrade.
apt autoremove --purge -y
apt autoclean
Review and remove any packages you installed for testing or no longer need. The lighter your system, the cleaner the upgrade.
Disable Third-Party Repositories
Third-party APT repositories are the most common cause of upgrade failures. They may not have packages for Noble (24.04), causing dependency conflicts that block the upgrade.
# List all active repositories
grep -r "^deb " /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null
# Disable all third-party repos by commenting them out
for f in /etc/apt/sources.list.d/*.list; do
if [ -f "$f" ]; then
echo "Disabling: $f"
sed -i 's/^deb /#deb /' "$f"
fi
done
# Also check for .sources files (DEB822 format)
for f in /etc/apt/sources.list.d/*.sources; do
if [ -f "$f" ]; then
echo "WARNING: Review manually: $f"
fi
done
Common third-party repos to disable include: Ondřej Surý's PHP PPA, Docker CE repositories, Node.js repositories, MariaDB repositories, and any custom PPAs. You will re-enable compatible versions of these after the upgrade completes.
Remove Held Packages
Packages marked as held will block the upgrade. Check for and remove any holds:
apt-mark showhold
# If any packages are held:
# apt-mark unhold package-name
Ensure do-release-upgrade Is Available
apt install update-manager-core -y
Verify the upgrade path is configured. Check /etc/update-manager/release-upgrades and ensure Prompt=lts is set:
cat /etc/update-manager/release-upgrades
# Should show: Prompt=lts
The Upgrade: Running do-release-upgrade
Protect Your SSH Session
If you are connected via SSH, an interrupted connection during the upgrade can leave your system in a broken state. Use screen or tmux to create a persistent session that survives connection drops.
# Install screen if not present
apt install screen -y
# Start a named screen session
screen -S upgrade
If your SSH connection drops during the upgrade, reconnect and reattach with screen -r upgrade. The upgrade process will continue running regardless of your SSH connection status. Note that do-release-upgrade also starts its own screen session and opens a backup SSH listener on port 1022 as a safety measure, but using your own screen session adds another layer of protection.
Launch the Upgrade
do-release-upgrade
If 24.04 is not yet offered (which can happen if Canonical has not enabled the upgrade path for all users), you can force it:
do-release-upgrade -d
The upgrade tool will display a summary of what it plans to do: packages to install, upgrade, and remove. Review this list carefully. If critical packages appear in the removal list, investigate before proceeding.
Configuration File Decisions
During the upgrade, dpkg will pause at several points asking about configuration files that have changed between versions. For each prompt, you must decide whether to keep your current version or install the package maintainer's version. Here is how to handle the most common files:
/etc/ssh/sshd_config — Keep your version if you have customized SSH settings (port, authentication methods, allowed users). The 24.04 version adds some new defaults, but your existing settings will work. After the upgrade, review the .dpkg-dist file to see if any new options are worth adopting.
/etc/nginx/nginx.conf — Keep your version. Your worker processes, connection limits, and performance tuning should be preserved. The maintainer's version rarely changes in ways that matter.
/etc/mysql/mysql.conf.d/mysqld.cnf — Keep your version if you have tuned buffer pool sizes, query cache settings, or other performance parameters. Review differences after the upgrade.
/etc/sysctl.conf — Keep your version. Your kernel parameter tuning (network buffers, file descriptors, etc.) should be preserved.
/etc/apt/sources.list — Accept the maintainer's version. The upgrade tool needs to replace this with 24.04 repository URLs. This is one of the few files where you should always accept the new version.
/etc/systemd/* — Generally accept the maintainer's version unless you have made specific systemd configuration changes. The 24.04 systemd configuration includes important improvements.
When in doubt, choose to keep your current version. The maintainer's version is saved as filename.dpkg-dist, so you can review and merge changes after the upgrade completes successfully.
Completing the Upgrade
The upgrade process typically takes 15 to 45 minutes depending on the number of installed packages and your server's performance. Using a MassiveGRID Dedicated VPS with dedicated CPU resources ensures the upgrade completes at a consistent speed without being affected by noisy neighbors. When the upgrade finishes, it will prompt you to reboot. Confirm the reboot and wait for the server to come back online.
Post-Upgrade Verification: Confirming Everything Works
After the reboot, log in and systematically verify every service. Do not assume the upgrade succeeded just because the server is reachable.
Verify the OS Version
lsb_release -a
# Should show: Ubuntu 24.04.x LTS (Noble Numbat)
uname -r
# Should show a 6.8.x kernel
Check Core Service Status
# Web server
systemctl status nginx
# or
systemctl status apache2
# Database
systemctl status mysql
# or
systemctl status mariadb
# PHP-FPM (note the version change)
systemctl status php8.3-fpm
# If this fails, the old version may still be referenced:
systemctl status php8.1-fpm
# Docker
systemctl status docker
docker ps
# Any other critical services from your pre-upgrade inventory
systemctl --failed
Compare the output of systemctl --failed against your pre-upgrade service list. Any service that was running before should be running now.
PHP Version Changes and Composer
This is where most web application upgrades hit trouble. Ubuntu 24.04 ships PHP 8.3, so your PHP-FPM pool configurations need updating.
# Check available PHP versions
ls /etc/php/
# If both 8.1 and 8.3 directories exist, migrate your pool configs
cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.3/fpm/pool.d/www.conf
# Copy any custom pool configurations similarly
# Update Nginx or Apache to use the new PHP-FPM socket
# In Nginx, change:
# fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
# To:
# fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
# Restart PHP-FPM and your web server
systemctl restart php8.3-fpm
systemctl restart nginx
# Verify PHP is working
php -v
php -m # Check loaded modules match what your app needs
# Update Composer dependencies
cd /var/www/your-app
composer install --no-dev
If Composer reports compatibility issues, review the specific errors. Common problems include extensions that need reinstalling for the new PHP version:
apt install php8.3-mysql php8.3-curl php8.3-mbstring php8.3-xml php8.3-zip php8.3-gd php8.3-intl php8.3-redis
MySQL Compatibility
Verify MySQL is running and your applications can connect:
mysql -u root -e "SELECT VERSION();"
mysql -u root -e "SHOW DATABASES;"
# Check for any deprecated features in your databases
mysqlcheck --all-databases --check-upgrade
If you encounter authentication issues after the upgrade, check whether the authentication plugin changed. MySQL 8.0 on 24.04 uses caching_sha2_password by default. If your applications expect mysql_native_password, you may need to update user authentication:
ALTER USER 'appuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
Python Virtual Environment Rebuilds
Python virtual environments are tied to the specific Python version they were created with. After upgrading from Python 3.10 to 3.12, existing virtualenvs will not work. Rebuild them:
# For each application with a virtualenv:
cd /var/www/your-python-app
# Remove the old virtualenv
rm -rf venv
# Create a new one with Python 3.12
python3 -m venv venv
# Reinstall dependencies
source venv/bin/activate
pip install -r requirements.txt
# If requirements.txt uses packages that dropped Python 3.10 syntax,
# you may need to update pinned versions
pip install --upgrade -r requirements.txt
Pay special attention to applications using distutils, which was removed in Python 3.12. Replace any distutils usage with setuptools equivalents.
Docker Verification
If Docker was installed from Docker's official repository (which you disabled before the upgrade), you need to re-enable it for Noble:
# Re-add Docker's repository for 24.04
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list
apt update && apt upgrade -y
# Verify Docker works
docker run hello-world
docker compose version
Check that all your containers are running and healthy:
docker ps -a
# Restart any containers that did not come back up
docker compose -f /path/to/docker-compose.yml up -d
Re-Enable Third-Party Repositories
For each third-party repository you disabled, check whether a Noble-compatible version exists. Update the repository URL to reference noble instead of jammy:
# Example: Updating a PPA or third-party repo
# Change 'jammy' to 'noble' in the repository definition
# Then:
apt update
If a repository does not support Noble yet, check whether the package is now available in Ubuntu's default repositories (many packages previously requiring PPAs are now included in 24.04).
Troubleshooting Common Upgrade Failures
Even with careful preparation, issues can arise. Here are the most common failures and their solutions.
Upgrade Fails to Start: "No new release found"
This usually means the upgrade path has not been enabled yet, or your /etc/update-manager/release-upgrades file has Prompt=never. Set it to Prompt=lts and try again with do-release-upgrade -d.
Dependency Conflicts During Upgrade
Third-party packages are almost always the cause. If the upgrade tool reports unresolvable dependencies, note the conflicting packages, cancel the upgrade, remove or purge those packages, and try again:
apt purge package-causing-conflict
do-release-upgrade
System Boots but Services Fail
Check the journal for error details:
journalctl -b -p err
# For a specific service:
journalctl -u nginx.service --since "1 hour ago"
Common causes include configuration syntax changes between versions, missing PHP extensions (pool configs referencing php8.1-fpm when only php8.3-fpm is installed), or changed socket paths.
Network Configuration Issues
Ubuntu 24.04 fully transitions to Netplan. If your server used /etc/network/interfaces (ifupdown), the upgrade should have migrated your configuration, but verify:
netplan get
ip addr show
# Compare with your expected IP configuration
If networking is broken, you may need to create a proper Netplan configuration in /etc/netplan/ and apply it:
netplan apply
GRUB or Boot Failures
If the server fails to boot after reboot, use your hosting provider's console access (not SSH) to troubleshoot. On MassiveGRID, you can access the VPS console through the control panel. Common fixes include reinstalling GRUB or selecting the previous kernel from the boot menu.
Partial Upgrade Recovery
If the upgrade was interrupted partway through, the package system may be in an inconsistent state. Try to complete it:
dpkg --configure -a
apt install -f
apt dist-upgrade
If this fails, restoring from your pre-upgrade snapshot or backup is usually faster than trying to manually fix a broken partial upgrade.
The Fresh Install Alternative
If the in-place upgrade seems too risky for your environment, or if your server has years of accumulated configuration drift, a fresh install may be the better path. The process involves provisioning a new Ubuntu 24.04 VPS, configuring it from scratch, migrating data, testing thoroughly, then switching traffic over.
For automating the setup of a fresh Ubuntu VPS, see our guide on automating Ubuntu VPS setup with Ansible. An Ansible playbook that captures your server's desired state makes fresh installs reproducible and fast. You define your packages, configurations, users, firewall rules, and service settings in code, then apply them to any new server in minutes.
The fresh install approach works especially well when combined with infrastructure-as-code practices. If you already have Ansible playbooks or shell scripts that set up your environment, updating them for 24.04 and running them on a new VPS is often faster and more reliable than an in-place upgrade.
Post-Upgrade Maintenance
Once the upgrade is confirmed successful and all services are running, complete these final housekeeping steps:
# Remove old kernels and packages
apt autoremove --purge -y
# Clean up leftover configuration files from removed packages
dpkg -l | grep '^rc' | awk '{print $2}' | xargs apt purge -y
# Review .dpkg-dist and .dpkg-old files
find /etc -name "*.dpkg-dist" -o -name "*.dpkg-old" 2>/dev/null
# Update your backup scripts and documentation
# Ensure automated backups are running on the upgraded system
# Run a final update to catch any packages released since the upgrade
apt update && apt upgrade -y
# Verify firewall rules are intact
ufw status verbose
# or
iptables -L -n
Review the .dpkg-dist files found above. These are the maintainer's versions of configuration files where you chose to keep your version. Compare them with your current configs using diff and merge any relevant changes, particularly new security defaults or performance improvements.
Upgrade Timeline and Planning
For a production server, plan the following timeline:
One week before: Complete the pre-upgrade checklist. Create and verify backups. Document all services and configurations. Test the upgrade on a temporary VPS.
Day of upgrade: Take a fresh backup and snapshot. Announce a maintenance window to stakeholders. Disable monitoring alerts for the duration (to avoid false alarms during reboot). Perform the upgrade during your lowest-traffic period.
Immediately after: Verify all services using your pre-upgrade inventory. Run your application test suite if you have one. Monitor error logs closely for the first few hours.
First week after: Monitor application performance and error rates. Compare resource utilization (CPU, RAM, disk I/O) with pre-upgrade baselines. Address any deprecation warnings in application logs.
Prefer Managed Upgrades?
Performing an LTS upgrade on a live production server requires expertise, careful planning, and availability to troubleshoot if something goes wrong. If you would rather focus on your application while someone else handles the infrastructure, MassiveGRID's fully managed hosting includes LTS upgrades as part of the service. The managed team plans the upgrade, tests it against your specific environment, schedules it during your preferred maintenance window, executes the migration, and verifies every service afterward. You get the benefits of running the latest LTS without the operational burden.
Whether you handle the upgrade yourself or let a managed team take care of it, moving to Ubuntu 24.04 LTS is a worthwhile investment. The improved kernel, updated runtimes, and strengthened security defaults provide a solid foundation for the next several years of your server's operational life. Take the time to prepare properly, follow each step methodically, and your upgrade will be a routine maintenance task rather than an emergency.