SSD Nodes Learn Hosting plans →
How to do am Matt ConnorBy Matt Connor · Updated 2026-10-02

How to Upgrade Ubuntu 24.04 to 26.04 VPS

Ubuntu 24.04 no go offer 26.04 until 26.04.1 land on 27 August 2026. See the safe upgrade order and VPS services wey fit break.

Wetin time you fit upgrade Ubuntu 24.04 to 26.04?

You fit upgrade Ubuntu 24.04 to 26.04 for VPS once 26.04.1 point release come out, and dem schedule am for 27 August 2026. Before that time, 24.04 server no go see the new release, and na intentional. Ubuntu 26.04 LTS (Resolute Raccoon) come out on 23 April 2026, but Canonical only opens the LTS-to-LTS upgrade path for the first point release. Na because that release don gather the install and upgrade bugs wey dem find for the first months. If this numbering dey new to you, 26.04.1 no be different Ubuntu; na the same 26.04 with four months of fixes wey dem add to the media, and na exactly why Canonical go first offer am to existing server.

Run the check for 24.04 box in early August 2026 and you go get this:

sudo do-release-upgrade
Checking for a new Ubuntu release
No new release found.

Dis na no fault for your server. /etc/update-manager/release-upgrades dey contain Prompt=lts for Ubuntu Server, and this mean say the tool go offer only the next long term support release, and only after im .1 point release don come out. If you set Prompt=normal, e go instead guide you through 24.10, 25.04 and 25.10 one after another. All of dem be interim releases wey don reach end of life. Leave am for lts and wait. Dates for Canonical's schedule fit change, so check am again if the date pass and nothing happen. Server wey still dey run 22.04 no fit make this jump direct, because the upgrader only ever offer the next LTS. So, upgrading 22.04 to 26.04 through 24.04 explain the first hop and the snapshot wey you need take before the second one.

Every command for below na command wey you go run yourself, for your own server, in the order wey dem give am. You no fit rehearse release upgrade for the same machine wey you dey upgrade. E go replace the kernel and the C library, and e need reboot to finish.

Make you upgrade at all?

Ubuntu 24.04 go continue receive standard security updates reach 2029, so working production server no dey under any deadline. Upgrade because you need wetin 26.04 get: PHP 8.5, PostgreSQL 18, MySQL 8.4 LTS, OpenSSH 10.2 or the 7.0 kernel. “The number went up” no be reason to touch machine wey dey serve customers.

No upgrade in place when any of these things dey true:

  • You never open your provider console (VNC or serial) and log in through am. That console na the only way to enter the box again if SSH spoil. If you discover say e no work when you don lock yourself out, e don too late.
  • You no fit afford one hour downtime and you no get rollback.
  • Your stack depend on third-party repository wey never publish for resolute yet.
  • Dem build the server by hand more than two years ago and nobody know wetin dey inside am.

The alternative often better: build fresh 26.04 VPS, install your stack and restore the data, then switch DNS once e answer correctly. You fit keep the old server running until the new one prove say e dey work, and rollback go be DNS change instead of restore. If you choose that way, start with the first ten minutes for new VPS and build the new box properly.

Step 1: make backup wey you fit restore from

Use two layers, because dem dey fail for different ways. Provider snapshot covers the whole disk and e fit restore within minutes, but dem dey take am while your databases still dey write, so na crash consistent backup e be instead of application consistent backup. File-level backup with restic, wey you store outside the server gives you individual files and another copy wey go survive if dem lock your account.

First, dump the databases by hand. Dump na the only database backup wey you fit trust without stopping the database.

sudo -u postgres pg_dumpall | sudo tee /var/backups/pg-all.sql > /dev/null
sudo mysqldump --all-databases --single-transaction --routines | sudo tee /var/backups/mysql-all.sql > /dev/null
sudo tar czf /var/backups/etc-before-upgrade.tgz -C / etc
sudo chmod 600 /var/backups/pg-all.sql /var/backups/mysql-all.sql

--single-transaction dey give consistent dump only for InnoDB tables. You need stop the database before you fit back up MyISAM tables. /etc tarball na the one wey you go actually use, because e contains every config file wey the upgrade go soon ask you questions about.

Backup wey you never restore na just guesswork. Pull one file out now, before you need am under pressure.

Step 2: patch 24.04 complete first

do-release-upgrade no go run for system wey get broken package state, and 24.04 wey patch only halfway go make every later failure harder to understand.

sudo apt update
sudo apt full-upgrade
sudo apt --purge autoremove
sudo dpkg --audit
apt-mark showhold

If dpkg --audit print nothing, e mean no package dey half-configured. If apt-mark showhold print nothing, e mean no package dey pinned to version wey fit block the upgrade. Release anything wey e list with sudo apt-mark unhold and the package name. Or accept say the hold get reason and stop here.

Reboot if the kernel change, so you fit upgrade from machine wey dey run the code e think say e dey run.

[ -f /var/run/reboot-required ] && sudo reboot

Then check disk space. The upgrader go download the complete new package set before e install anything. If space no dey enough, e go stop and show the filesystem name.

df -h / /boot

If free space for / dey below about 5 GB, na there this problem fit happen. If /boot dey below 300 MB, e go fail later during kernel installation with No space left on device. Old kernels usually cause this problem, and sudo apt --purge autoremove go clear dem.

One more thing you need stop before you start: if automatic security updates run while the process dey go on, dem go hold the dpkg lock, and the release upgrader go stop with Could not get lock /var/lib/dpkg/lock-frontend. Run sudo systemctl stop unattended-upgrades first, then start the upgrade again when e finish.

Step 3: check third-party repositories and pinned packages

do-release-upgrade go disable every apt source wey no be Ubuntu own, because package wey dem build for noble fit spoil resolute system. E go enable again the ones wey e recognise, then leave the remaining ones commented out. Know wetin you carry before the tool decide for you.

ls /etc/apt/sources.list.d/
grep -rhE '^(deb |Types:|URIs:|Suites:)' /etc/apt/sources.list.d/
ubuntu-security-status --thirdparty
ls /etc/apt/preferences.d/

Ubuntu 24.04 dey use two formats for that directory: the old one-line .list files, and deb822 .sources files wey get Types: and Suites: fields. Upgrade go disable both of dem. ubuntu-security-status --thirdparty list the packages wey dey installed but no Ubuntu archive provide, so na the correct count of wetin you add by hand. Anything inside /etc/apt/preferences.d/ na pin, and pin wey dem write for noble go keep selecting old package for the new release.

For each third-party repository, confirm say the vendor don publish am for the new codename before you start. Docker suites dey listed for https://download.docker.com/linux/ubuntu/dists/, and other vendors dey expose the same directory. Source wey point to suite wey no exist go show this for the first apt update after the upgrade:

E: The repository 'https://download.docker.com/linux/ubuntu resolute Release' does not have a Release file.

Leave that source disabled until the vendor publish am. If you edit the codename to one wey the vendor build package for, you fit install packages wey link against wrong system libraries.

Step 4: run the upgrade inside tmux, no be plain SSH shell

If your connection drop while do-release-upgrade dey run for plain login shell, process go receive SIGHUP and die halfway while e dey unpack. That one fit leave dpkg half configured, and server fit lose working network stack wey you need to connect back. Run am inside terminal multiplexer instead, so process go continue dey alive for server when your client disconnect.

sudo apt install -y tmux
tmux new -s upgrade

Inside that session:

sudo ufw allow 1022/tcp
sudo do-release-upgrade

The upgrader go start second SSH daemon for port 1022 before e change anything, and e go tell you:

To make recovery in case of failure easier, an additional sshd will be started on port '1022'. If anything goes wrong with the running ssh you can still connect to the additional one.

E no go open your firewall for that port, because opening firewall hole without asking you fit cause bad surprise. Open 1022 yourself before you start, then close am when you finish with sudo ufw delete allow 1022/tcp. Remember say your provider fit run another firewall for e control panel, outside the server.

If connection still drop, log in again and run tmux attach -t upgrade. The upgrade don continue while you dey away. If e no continue, and you come back meet dpkg wey never finish configuration or apt sources wey partly dey noble and partly dey resolute, how to recover failed release upgrade explain how to repair package state and know when to stop the repair and restore the snapshot instead.

Step 5: make you answer configuration file prompts with care

dpkg only dey prompt for files wey you or script don change. So every prompt na file wey you edit intentionally, and if you press enter just to make am disappear, na so hardened server fit quietly turn to default one.

Configuration file '/etc/ssh/sshd_config'
 ==> 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
 The default action is to keep your current version.
*** sshd_config (Y/I/N/O/D/Z) [default=N] ?

Press D first, every time. Read wetin change, then keep your version with N. The default don already be N, and na the safe answer be that, because your file dey work today while the packaged one never run for this machine.

If you keep your file, e get cost: you no go get the new defaults. Reconcile am later, after the box don come up and you no dey under time pressure.

sudo find /etc -name '*.dpkg-dist' -o -name '*.dpkg-new'

Each file wey dem list na maintainer's version, saved beside your own. Diff dem one by one, then copy the settings wey matter. Pay extra attention to two: /etc/ssh/sshd_config, because wrong answer fit end your session, and your web server config, because wrong answer fit take the sites down.

The upgrade still go ask which services to restart, through needrestart. Accept the full list. If daemon still dey run against shared library file wey dem don delete from disk, e fit crash for some later request, when you no dey monitor am.

Step 6: reboot, then check the machine

sudo reboot

When e come back:

lsb_release -a
uname -r
systemctl --failed
journalctl -p err -b --no-pager | head -50
sudo apt update && sudo apt full-upgrade
sudo apt --purge autoremove

lsb_release -a suppose report Release: 26.04 and Codename: resolute. uname -r suppose show 7.0 kernel. systemctl --failed suppose list zero units, and anything wey e list na your next work. The final apt update go pull the updates wey dem publish since dem build the release images.

PostgreSQL 16 go 18: the cluster wey quietly remain behind

Ubuntu 24.04 dey ship PostgreSQL 16 and 26.04 dey ship PostgreSQL 18. The upgrade go install 18 beside 16 but e no go move your data. Debian's postgresql-common layer go create new empty cluster for the new major version on the next free port, so 16 go keep port 5432 with all your data while 18 go remain empty for 5433. Your application go continue to talk to 5432 and nothing go look wrong. Na why people dey discover this months later.

pg_lsclusters

If you see two clusters listed, e mean say you never migrate. Do am when you fit stop the application:

sudo pg_dropcluster --stop 18 main
sudo pg_upgradecluster 16 main
pg_lsclusters
sudo -u postgres vacuumdb --all --analyze-only

First drop the empty 18 cluster, because pg_upgradecluster no go write inside target cluster wey already exist. The default method go dump 16 and reload am into 18, so you need free disk space wey roughly match the database size. -m upgrade uses pg_upgrade instead, and e dey much faster for large database. When e finish, read the Port column: the new cluster go take over 5432, while the old one go remain stopped. Run the analyze pass yourself, because freshly loaded cluster no get statistics and the first queries go slow.

Test the application against the new cluster for some days. Na only after that you suppose remove the old one:

sudo pg_dropcluster 16 main
sudo apt purge postgresql-16

The old cluster's data directory na the fastest rollback option wey you get. No delete am on upgrade day.

MySQL 8.0 to 8.4: option wey dem remove and dey stop the server

26.04 go move MySQL from 8.0 to 8.4 LTS, and two changes fit catch servers.

First, mysqld no go start when its config get option wey the new version don remove. default_authentication_plugin na the common one, because plenty old guides tell people to set am. The service go fail, and journalctl -u mysql -n 50 go name the unknown variable directly. Delete that line from the file under /etc/mysql/mysql.conf.d/, then sudo systemctl start mysql.

Second, mysql_native_password plugin no dey enabled by default again for 8.4, so account wey still dey use am no fit log in at all. Check while you still dey run 8.0:

sudo mysql -e "SELECT user, host, plugin FROM mysql.user;"

Move every account wey show mysql_native_password across before the upgrade, then update the password for your application config:

ALTER USER 'appuser'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'a new password';

If client library too old to speak caching_sha2_password, you fit switch the old plugin on again for 8.4 by adding mysql_native_password=ON under [mysqld]. Treat am as temporary bridge with end date, because dem dey remove the plugin completely.

PHP 8.3 go 8.5: una vhost dey point to socket wey don disappear

24.04 release PHP 8.3 and 26.04 release PHP 8.5. Packages dey install for versioned paths, and nothing dey rewrite your web server config. An nginx vhost wey get fastcgi_pass unix:/run/php/php8.3-fpm.sock; dey point now to socket wey no process dey create, so every PHP request dey return 502 and nginx error log dey talk:

connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory)

Point am to the new socket, test the config, then reload:

sudo sed -i 's/php8.3-fpm.sock/php8.5-fpm.sock/' /etc/nginx/sites-available/example.com
sudo nginx -t
sudo systemctl reload nginx

For Apache with mod_php, the symptom dey different: Apache no go start at all, and sudo apache2ctl -t dey report say e no fit load libphp8.3.so because the file no dey exist. The enabled module na symlink to package wey don comot.

sudo a2dismod php8.3
sudo a2enmod php8.5
sudo systemctl restart apache2

If na LAMP stack for Ubuntu 24.04 you use build the server, check both paths, because the guide leave you with versioned module name and versioned socket.

Your php.ini tuning no dey carry over too. memory_limit, upload_max_filesize and anything else wey you set dey inside /etc/php/8.3/, and the new tree start with defaults. Compare the two files and copy the values across by hand. If you copy the whole old file over the new one, e go carry 8.3 defaults enter 8.5 install. Then run php -m and compare: extension wey dem install as php8.3-redis need its php8.5- package, and if e come from PPA, the upgrader don disable that source, so the extension simply no dey.

Certificates need one separate check. Run sudo certbot renew --dry-run after the upgrade. E dey test the complete renewal path, including the web server reload hook, without touching the live certificate. If hook dey call service name or binary wey don change, e go fail here where you fit see am, instead of failing quietly after 60 days. Certbot with Let's Encrypt for nginx explain how those hooks suppose look.

SSH: failure wey go end the session wey you dey work inside

The sshd_config prompt na where people dey lock themselves out. If you answer Y, e go install the maintainer file, and discard your PermitRootLogin, PasswordAuthentication, AllowUsers, Port plus every other line wey you add. If your firewall allow only custom port and the packaged config dey listen on 22, the next connection go get refused, and the session wey you dey inside go be the last one wey you get.

Prevent am before you upgrade. /etc/ssh/sshd_config for 24.04 dey start with Include /etc/ssh/sshd_config.d/*.conf, and OpenSSH dey keep the first value wey e read for each setting. So, any drop-in wey dem include for the top go override anything below. Move your settings go file wey dpkg no own:

sudo tee /etc/ssh/sshd_config.d/99-local.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy
EOF
sudo chmod 644 /etc/ssh/sshd_config.d/99-local.conf
sudo sshd -t && sudo systemctl restart ssh

Once nothing inside /etc/ssh/sshd_config belong to you, that prompt no go matter again. Any answer go preserve your settings, because dem dey inside another file.

Custom port need one more check, because e fit no dey where you think say e dey:

systemctl is-enabled ssh.socket

If that command print enabled, systemd own the listening port, and the Port line inside sshd_config no dey apply. Ubuntu don dey use socket activation for sshd since 22.10. Na this make Port 2222 edit look like say e do nothing. Set am for the socket unit instead, with sudo systemctl edit ssh.socket:

[Socket]
ListenStream=
ListenStream=2222

The empty ListenStream= dey required. E clear the inherited value. If you no include am, the socket go listen on 22 as well as 2222. Apply am with sudo systemctl daemon-reload && sudo systemctl restart ssh.socket.

After the upgrade, before you close the session wey you dey inside:

sudo sshd -t
sudo systemctl status ssh.socket --no-pager
sudo ss -lntp | grep -E ':(22|2222)'

Then open second terminal for your own machine and log in again. Working shell for that second terminal na the only proof wey count. Keep the first session open until you confirm am. SSH hardening for VPS explain the settings wey worth keeping inside that drop-in.

If e don too late already, your provider web console go give you login wey no use SSH at all. Log in there, fix the config, run sudo sshd -t, then restart the service. That console na exactly why you suppose test console access before upgrade, instead of during the upgrade.

FAQ

Why do-release-upgrade dey talk say "No new release found" for Ubuntu 24.04?

Na because /etc/update-manager/release-upgrades get Prompt=lts for Ubuntu Server. This setting dey offer the next long term support release only after the first point release don come out. Ubuntu 26.04 LTS ship on 23 April 2026, and dem schedule 26.04.1 for 27 August 2026. Until that day, 24.04 server no go see any new release. Leave the setting as e dey instead of changing am to Prompt=normal, because that one go pass you through the interim releases.

I must reboot the server to finish the upgrade?

Yes. The upgrade install new kernel, new C library, and new init system. The running system go continue to use the old ones until e restart. do-release-upgrade go ask you to reboot at the end. If machine continue to run until "later", e go dey use mixture of two releases. After e come back, check uname -r for the new kernel and systemctl --failed for services wey no survive.

I suppose upgrade in place or build fresh 26.04 server?

Build fresh when you fit. New VPS let you install the stack, restore the data, and test everything while the old server still dey serve traffic. That way, rollback na DNS change instead of restore from backup. Upgrade in place when server get state wey hard to move, when provider dey charge per machine, or when you get snapshot and confirmed console access. The in-place path don dey used plenty times, but e be one-way door for the time wey e dey run.

Wetin go happen if my SSH connection drop during the upgrade?

For plain login shell, process go receive SIGHUP and die halfway. That one go leave dpkg half configured. Start am inside tmux or screen and process go survive. Then reconnect and run tmux attach -t upgrade to continue from where e stop. The upgrader also start spare SSH daemon for port 1022 as another way to enter. But e no open firewall for that port, so allow 1022 yourself first and close am after.

My PHP site dey return 502 after upgrade. Wetin spoil?

PHP FPM socket path change with the version. Ubuntu 24.04 dey run PHP 8.3, while 26.04 dey run PHP 8.5. So /run/php/php8.3-fpm.sock no longer dey exist, but your nginx vhost still dey refer to am. nginx error log go show connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory). Update fastcgi_pass to the 8.5 socket, run sudo nginx -t, then reload nginx. For Apache with mod_php, the matching fix na sudo a2dismod php8.3 followed by sudo a2enmod php8.5 and restart.