When Ubuntu 24.04 Fit Upgrade to 26.04 for VPS
Ubuntu 24.04 no go offer 26.04 until 26.04.1 land on 27 August 2026. See the safe upgrade order and which VPS services fit break.
When you fit upgrade Ubuntu 24.04 go 26.04?
You fit upgrade Ubuntu 24.04 go 26.04 for a VPS once 26.04.1 point release don release, wey dem schedule for 27 August 2026. Before then, 24.04 server no go see the new release, and na intentional. Ubuntu 26.04 LTS (Resolute Raccoon) don release for 23 April 2026, but Canonical only opens the LTS-to-LTS upgrade path for the first point release, because that release gather the install and upgrade bugs wey dem find for the first months.
Run the check for 24.04 box for early August 2026 and you go get this:
sudo do-release-upgradeChecking for a new Ubuntu release
No new release found.This no be fault for your server. /etc/update-manager/release-upgrades get Prompt=lts for Ubuntu Server, wey mean say the tool go offer only the next long term support release, and only after its .1 point release don exist. If you set Prompt=normal, e go instead take you through 24.10, 25.04 and 25.10 one after another, and all those interim releases don reach end of life. Leave am for lts and wait. Dates for Canonical's schedule fit change, so check am again if the day pass and nothing happen.
Every command wey follow na command you go run yourself, for your own server, in the order wey dem give. You no fit rehearse a release upgrade for the 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 receive standard security updates reach 2029, so production server wey dey work no dey under any deadline. Upgrade because you need something wey 26.04 carry: 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 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 break, and if you discover say e no work after dem lock you 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
resoluteyet. - Dem build the server by hand over 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 go keep the old server running until the new one prove itself, and rollback go be DNS change instead of restore. If you choose this 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 dey cover the whole disk and fit restore within minutes, but e dey happen while your databases dey write, so na crash consistent e be, no be application consistent. File-level backup with restic, wey you store outside the server go give you individual files and another copy wey go survive if dem lock your account.
Dump the databases by hand first. 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 back up MyISAM tables. The /etc tarball na the one you go actually use, because e contain every config file wey the upgrade go soon ask you questions about.
Backup wey you never restore before na guesswork. Pull one file from am now, before you need am under pressure.
Step 2: patch 24.04 completely first
do-release-upgrade no dey run for system wey package state spoil, and half-patched 24.04 dey make every later failure harder to understand.
sudo apt update
sudo apt full-upgrade
sudo apt --purge autoremove
sudo dpkg --audit
apt-mark showholddpkg --audit wey print nothing mean say no package dey half configured. apt-mark showhold wey print nothing mean say 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 go upgrade from machine wey dey run the code wey e believe say e dey run.
[ -f /var/run/reboot-required ] && sudo rebootThen check disk space. The upgrader go download the complete new package set before e install anything, and e go abort with message wey name the filesystem if space no dey enough.
df -h / /bootIf free space for / dey below about 5 GB, na there this problem dey happen. A /boot below 300 MB go fail later, during kernel install, with No space left on device. Old kernels na usually the cause, and sudo apt --purge autoremove dey clear dem.
One more thing to stop before you start: if automatic security updates fire while the process dey run, 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 am again when you don 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 rest commented out. Know wetin you dey 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 dey disable both of dem. ubuntu-security-status --thirdparty dey list the installed packages wey no Ubuntu archive provide, so e show the honest count of wetin you add by hand. Anything wey dey inside /etc/apt/preferences.d/ na pin, and pin wey dem write for noble go continue to choose 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 during 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 actually build, na so you fit install packages wey dem link against the 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 inside plain login shell, process go receive SIGHUP and die halfway through unpacking. That one go leave dpkg half configured, and the server fit no longer get working network stack wey you fit use reconnect. Run am inside terminal multiplexer instead, so process go remain alive for server when your client disconnect.
sudo apt install -y tmux
tmux new -s upgradeInside that session:
sudo ufw allow 1022/tcp
sudo do-release-upgradeThe upgrader go start second SSH daemon for port 1022 before e change anything, and e go talk am:
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 for am go be bad surprise. Open 1022 by yourself before you start, and 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 continue to run while you no dey there.
Step 5: answer configuration file prompts with care
dpkg only prompts for files wey you or script don change. So every prompt na for file wey you edit deliberately, and if you press enter just to make am disappear, na so hardened server fit quietly turn to default server.
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 already be N, and na the safe answer, because your file dey work now, while the packaged one never run for this machine.
If you keep your file, you no go get the new defaults. Reconcile dem afterwards, after the box don come up and you no dey under time pressure.
sudo find /etc -name '*.dpkg-dist' -o -name '*.dpkg-new'Every file wey list na the maintainer 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 also ask which services to restart, through needrestart. Accept the full list. If daemon still dey use shared library file wey don delete from disk, e fit crash for some later request, when you no dey monitor am.
Step 6: reboot, den check the machine
sudo rebootWhen 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 autoremovelsb_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 job. 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 dey behind
Ubuntu 24.04 dey release PostgreSQL 16, while 26.04 dey release PostgreSQL 18. The upgrade installs 18 beside 16 but e no move your data. Debian's postgresql-common layer creates new empty cluster for the new major version for the next free port. So, 16 still dey use port 5432 with all your data, while 18 dey empty for 5433. Your application continues to talk to 5432 and nothing go look wrong. Na why people dey discover am months later.
pg_lsclustersIf you see two clusters for the list, 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-onlyFirst drop the empty 18 cluster, because pg_upgradecluster no go write inside target cluster wey already exist. The default method dumps 16 and reloads the data 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 by 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-16The old cluster's data directory na the fastest rollback option wey you get. No delete am on upgrade day.
MySQL 8.0 go 8.4: option wey dem remove fit stop server
26.04 dey move MySQL from 8.0 go 8.4 LTS, and two changes fit catch servers.
First, mysqld no go start if e see option for config wey the new version don remove. default_authentication_plugin na the common one, because plenty old guides tell people make dem 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 am 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 phase out the plugin completely.
PHP 8.3 go 8.5: your vhosts still point to socket wey don disappear
24.04 ships PHP 8.3 and 26.04 ships PHP 8.5. The packages install for versioned paths, and nothing rewrite your web server config. An nginx vhost wey get fastcgi_pass unix:/run/php/php8.3-fpm.sock; now dey point to socket wey no process dey create, so every PHP request dey return 502 and nginx error log dey talk say:
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 nginxFor 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 apache2If you build the box from LAMP stack for Ubuntu 24.04, 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 bring 8.3 defaults enter the 8.5 install. Then run php -m and compare: extension wey 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 dey missing.
Certificates need one check of their own. 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 call service name or binary wey don change, e go fail here for your front, instead of failing silently 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
Na the sshd_config prompt dey make people lock themselves out. If you answer Y, e go install the maintainer's file, wey go remove your PermitRootLogin, PasswordAuthentication, AllowUsers, Port and 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 refuse, 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, drop-in wey dem include for top go override anything wey dey below. Move your settings enter 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 sshOnce nothing inside /etc/ssh/sshd_config belong to you, that prompt no matter again: any answer go keep 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.socketIf that command print enabled, systemd own the listening port, and the Port line inside sshd_config no dey work. Ubuntu don dey use socket activation for sshd since 22.10, and na why editing Port 2222 fit look like say e no do anything. Set am for the socket unit instead, with sudo systemctl edit ssh.socket:
[Socket]
ListenStream=
ListenStream=2222The empty ListenStream= dey required. E clear the inherited value. Without am, the socket go listen on 22 and 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. Leave 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, your provider's web console go give you login wey no use SSH at all. Log in there, fix the config, run sudo sshd -t, restart the service. Na that console make you test console access before upgrade, instead of waiting until upgrade time.
FAQ
Why do-release-upgrade dey talk say "No new release found" for Ubuntu 24.04?
Because /etc/update-manager/release-upgrades get Prompt=lts for Ubuntu Server, and that setting go offer the next long term support release only after the first point release don dey available. Ubuntu 26.04 LTS come out on 23 April 2026, and dem schedule 26.04.1 for 27 August 2026. Before that day, 24.04 server no go see any new release. Leave the setting as e be instead of switching to Prompt=normal, because that one go route you through the interim releases.
I need 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 use the old ones until e restart. do-release-upgrade go ask make you reboot at the end, and machine wey you leave running until "later" go dey run mixture of two releases. After e come back, check uname -r for the new kernel and systemctl --failed for services wey no survive.
Make I upgrade in place or build fresh 26.04 server?
Build fresh when you fit. New VPS go 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 the server hold state wey hard to move, when provider dey bill per machine, or when you get snapshot and tested console access. The in-place path don dey used many 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, and dpkg go remain 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, then close am afterwards.
My PHP site dey return 502 after upgrade. Wetin spoil?
The 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, while your nginx vhost still dey reference am. The 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 equivalent fix na sudo a2dismod php8.3, followed by sudo a2enmod php8.5 and restart.