How to Downgrade Ubuntu 26.04 LTS to 25.04

Unsupported two-hop downgrade Ubuntu 26.04 LTS to 25.04 via 25.10 using apt pinning and aptitude—no data loss under /home on our VirtualBox VM—reboot between hops, Python and GRUB failures, libc6 hybrid state, and when to restore a snapshot instead.

Published

Updated

Read time 8 min read

Reviewed byDeepak Prasad

Downgrade Ubuntu 26.04 LTS to 25.04 with apt pinning and aptitude on a terminal

Canonical does not provide do-release-downgrade. If you upgraded to Ubuntu 26.04 LTS and want Ubuntu 25.04 (Plucky Puffin) back, the supported answer is restore a snapshot or reinstall—not reverse the release in place.

Community guides describe retargeting apt sources, pinning an older suite above installed packages, and running aptitude dist-upgrade. I tested the full reverse of our upgrade walkthrough from Ubuntu 25.04 to 26.04 LTS on a VirtualBox VM: 26.04 → 25.10, reboot, then 25.10 → 25.04. Marker files under /home and in /root were still present at the end—no data loss on that VM.

Both hops eventually changed PRETTY_NAME in /etc/os-release, but neither hop produced a clean system equal to a fresh install. Expect Python conflicts, broken GRUB scripts, a stuck libc6, and leftover kernels from every release you passed through.

Tested on: VirtualBox VM (server1); started on Ubuntu 26.04 LTS; finished on Ubuntu 25.04; kernel 7.0.0-27-generic still running after final hop.

WARNING
Take a hypervisor snapshot or filesystem backup before hop one. If grub-mkconfig disappears or libc6 downgrade fails, restore the snapshot instead of continuing on a hybrid system. See backup and rollback options.

Quick command summary

Downgrading is the reverse of upgrading: for each hop you add an apt pin file, swap the suite codename in ubuntu.sources, then let aptitude dist-upgrade pull older package versions. Keep this table open while you work through the hop sections.

Task Command
Hop 1 pin file /etc/apt/preferences.d/questing-pin → suites questing*
Hop 1 sources sudo sed -i 's/resolute/questing/g' /etc/apt/sources.list.d/ubuntu.sources
Downgrade sudo aptitude dist-upgrade -y
Fix dpkg sudo dpkg --force-confdef --force-confold --configure -a
Force release flip sudo apt install --allow-downgrades libc6=… base-files=…
Reboot between hops sudo reboot then uname -r
Hop 2 pin file /etc/apt/preferences.d/plucky-pin → suites plucky*
Hop 2 sources sudo sed -i 's/questing/plucky/g' /etc/apt/sources.list.d/ubuntu.sources
Fix GRUB sudo apt install --reinstall grub-common grub2-common grub-pc-bin

Two-hop path

You cannot jump from resolute (26.04) straight to plucky (25.04) in one aptitude run without hitting dependency dead ends. Mirror the supported upgrade path in reverse: land on 25.10 first, reboot, then retarget to 25.04.

Phase From To Pin file Sources codename
Hop 1 26.04 LTS 25.10 questing-pin questing
Reboot Clear reboot flag; check kernel
Hop 2 25.10 25.04 plucky-pin plucky
Reboot Pick a kernel that matches 25.04

Hop one took about 34 minutes plus recovery time. Hop two took about 30 minutes plus a GRUB reinstall.


Prerequisites

This workflow is unsupported and can leave hybrid package states. Treat the list below as a lab checklist—not a production runbook—unless you have a snapshot to restore.

  • Ubuntu 26.04 LTS at the start (my VM had been upgraded from 25.04 earlier).
  • sudo and a working network mirror.
  • aptitude installed.
  • A snapshot or full backup—mandatory for anything beyond a disposable lab (see next section).

Backup and rollback options

Restoring a backup is the supported rollback. apt pinning in this guide is lab-only documentation—use it to understand what went wrong on an upgrade, not as your only safety net.

Method Best for Guide
Hypervisor snapshot VirtualBox, VMware, Proxmox Snapshot before hop one; restore if downgrade breaks GRUB or Python
LVM snapshot Systems on LVM (my test VM used ubuntu-vg) Linux LVM snapshot backup and restore
fsarchiver archive Full root copy to external media Clone or backup a Linux partition with fsarchiver

Save the partition table before retargeting apt sources if layout or boot entries might change: backup and restore the partition table in Linux.


Pre-downgrade checks

Capture your starting release, running kernel, free disk space, and a copy of ubuntu.sources before you edit apt metadata. If hop one goes wrong, you can restore the sources file from ~/ubuntu.sources.backup.

bash
cat /etc/os-release
uname -r
df -h /
sudo cp /etc/apt/sources.list.d/ubuntu.sources ~/ubuntu.sources.backup

Starting point on my VM:

text
PRETTY_NAME="Ubuntu 26.04 LTS"
VERSION_CODENAME=resolute
6.17.0-40-generic

Hop 1 — downgrade 26.04 LTS to 25.10

apt normally prefers the newest package versions from your configured suites. Pinning gives questing a higher priority than installed resolute packages so aptitude can downgrade thousands of .deb files in one pass.

Pin questing and retarget sources

Create /etc/apt/preferences.d/questing-pin with three stanzas—one each for questing, questing-updates, and questing-security. Priorities 1001–1003 tell apt to prefer those suites over what is already installed.

Create /etc/apt/preferences.d/questing-pin:

text
Package: *
Pin: release n=questing
Pin-Priority: 1001

Package: *
Pin: release n=questing-updates
Pin-Priority: 1002

Package: *
Pin: release n=questing-security
Pin-Priority: 1003

The sed command replaces every resolute codename in ubuntu.sources with questing so apt pulls 25.10 packages. Then aptitude dist-upgrade resolves the downgrade graph; -o Aptitude::Delete-Unused=false avoids aggressive autoremove mid-hop.

bash
sudo sed -i 's/resolute/questing/g' /etc/apt/sources.list.d/ubuntu.sources
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive aptitude dist-upgrade -y -o Aptitude::Delete-Unused=false

Hop 1 issues and fixes

Hop one rarely finishes without manual recovery. On my VM aptitude hit apt AutoRemover bugs, Python file conflicts, and a stuck os-release until I forced core packages. Work through each symptom below if your run stops mid-way.

apt AutoRemover error on dry-run — use aptitude instead:

text
E: Internal Error, AutoRemover broke stuff

Python 3.14 overwrite conflict mid-run:

text
trying to overwrite '/usr/lib/python3.14/shutil.py', which is also in package libpython3.14-minimal

gdm3 interactive prompt blocked apt -f install until I ran:

bash
sudo DEBIAN_FRONTEND=noninteractive dpkg --force-confdef --force-confold --configure -a
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-downgrades -f \
  -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"

/etc/os-release still 26.04 until I installed core packages explicitly:

bash
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-downgrades \
  -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" \
  libc6=2.42-0ubuntu3.1 base-files=14ubuntu3 ubuntu-minimal

Result:

text
PRETTY_NAME="Ubuntu 25.10"
VERSION_CODENAME=questing

Files under /home were unchanged.


Reboot between hops

Do not start hop two while /var/run/reboot-required is set or while GRUB still defaults to a 26.04 kernel. Reboot after hop one, confirm PRETTY_NAME shows 25.10, then swap pin files and sources for plucky.

On my VM, GRUB booted the wrong kernel:

text
uname -r
7.0.0-27-generic

That is the Linux 7.0 image left from 26.04, not the 6.17 kernel shipped with 25.10. The system ran 25.10 packages on a 7.0 kernel until I documented it—ideally set GRUB_DEFAULT to 6.17.0-40-generic or purge linux-image-7.0.0-27-generic before hop two.

bash
cat /var/run/reboot-required || echo "OK"
cat /etc/os-release | grep PRETTY
text
OK
PRETTY_NAME="Ubuntu 25.10"

Hop 2 — downgrade 25.10 to 25.04

Remove the questing pin so it does not fight the new plucky priorities. The pattern is the same as hop one: pin file, sed on ubuntu.sources, apt update, then aptitude dist-upgrade with non-interactive dpkg flags.

Add /etc/apt/preferences.d/plucky-pin (same pattern with plucky, plucky-updates, plucky-security at priorities 1001–1003), then run:

bash
sudo rm /etc/apt/preferences.d/questing-pin
sudo sed -i 's/questing/plucky/g' /etc/apt/sources.list.d/ubuntu.sources
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive aptitude dist-upgrade -y \
  -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"

Plucky (25.04) was still on archive.ubuntu.com during my test—not old-releases yet. If your mirror no longer carries plucky, switch to old-releases.ubuntu.com before apt update.

Hop 2 issues and fixes

Hop two broke GRUB on my VM and left libc6 at a 25.10 version even after os-release said 25.04. Expect similar hybrid states rather than a pristine Plucky install.

GRUB scripts missing after the aptitude run — grub-pc, kdump-tools, and linux-image-6.14.0-37-generic failed configuration:

text
/usr/sbin/update-grub: 3: exec: grub-mkconfig: not found
grub-mkdevicemap: command not found

Fix:

bash
sudo DEBIAN_FRONTEND=noninteractive apt-get install --reinstall -y \
  grub-common grub2-common grub-pc-bin
sudo DEBIAN_FRONTEND=noninteractive dpkg --force-confdef --force-confold --configure -a

libc6 stuck at 2.42 (25.10) while /etc/os-release already said 25.04:

bash
apt-cache policy libc6
text
Installed: 2.42-0ubuntu3.1
Candidate: 2.41-6ubuntu1.2

Explicit downgrade refused:

text
gnu-coreutils:amd64 PreDepends libc6 (>= 2.42)

So hop two changed base-files and ubuntu-minimal but left a 25.10-era C library—a hybrid state you should expect, not fight, unless you are prepared to remove conflicting metapackages.


Post-downgrade verification

Run these after hop two to see what actually changed: release metadata, running kernel, core library versions, leftover kernels in /boot, and obsolete packages from releases you passed through.

bash
cat /etc/os-release
uname -r
dpkg -l libc6 base-files
dpkg --audit
ls /boot/vmlinuz-*
apt list '?obsolete'
do-release-upgrade -c

Final values on my VM:

text
PRETTY_NAME="Ubuntu 25.04"
VERSION_CODENAME=plucky
7.0.0-27-generic
libc6 2.42-0ubuntu3.1
base-files 13.6ubuntu2
text
/boot/vmlinuz-6.14.0-37-generic
/boot/vmlinuz-6.17.0-40-generic
/boot/vmlinuz-7.0.0-27-generic
26 obsolete packages
Your Ubuntu release is not supported anymore.   (do-release-upgrade -c)

dpkg --audit was empty after the GRUB reinstall. Review leftover packages with the steps in remove obsolete packages on Ubuntu before bulk purging.


Troubleshooting

Use this table to map a symptom to the hop where I saw it and the recovery command that unblocked the downgrade on server1.

Symptom Hop Fix
AutoRemover broke stuff 1 Use aptitude dist-upgrade
Python 3.14 overwrite 1 dpkg --configure -a + apt -f install --allow-downgrades
custom.conf prompt 1 dpkg --force-confdef --force-confold
os-release unchanged 1–2 Install libc6 + base-files from target suite
Boots Linux 7.0 on 25.10/25.04 packages Reboot Change GRUB default; purge linux-image-7.0.0-27-generic
grub-mkconfig: not found 2 Reinstall grub-common grub2-common grub-pc-bin
libc6 won't go below 2.42 on 25.04 2 Hybrid state—coreutils-from-uutils chain; snapshot restore if apps break
Many obsolete packages Both apt list '?obsolete'; purge carefully

Data on /

The downgrade did not remove files under /home. apt downgrades packages under /usr and merges config under /etc; it does not wipe home directories.

You can still lose access to that data if GRUB or libc6 leaves the system unbootable—restore a hypervisor snapshot, LVM snapshot, or fsarchiver archive instead of pushing further on a broken hybrid system.


References


Summary

Downgrading Ubuntu 26.04 to 25.04 takes two unsupported hops—26.04 → 25.10, reboot, then 25.10 → 25.04—using suite retargeting, apt pinning, and aptitude dist-upgrade. On my VirtualBox VM both hops changed /etc/os-release, preserved files in /home with no data loss, and still left a messy system: wrong default kernel, hybrid libc6, 26 obsolete packages, and a broken GRUB until I reinstalled grub-common.

If you have a snapshot or fsarchiver archive from before the upgrade, restore it. Use this guide only in a lab, reboot between hops, and treat every error message as a signal to stop and roll back rather than push through.


Frequently Asked Questions

1. Does Ubuntu officially support downgrading 26.04 to 25.04?

No. Canonical only supports upgrades via do-release-upgrade. Downgrades use unsupported apt pinning and leave hybrid package states. A VM snapshot or reinstall is the reliable rollback.

2. Why downgrade 26.04 to 25.10 first instead of jumping straight to 25.04?

Mirrors the supported upgrade path in reverse. Each single-hop downgrade already broke Python, GRUB, and libc dependencies on my test VM—stacking both hops in one aptitude run would be harder to recover from.

3. Will my files on / survive an apt-based downgrade?

On my VM, marker files in /home/golinuxcloud and /root were untouched through both hops. apt rewrites system packages, not user home trees—but a broken libc or GRUB can still lock you out until you fix or restore a snapshot.

4. Why did my VM boot Linux 7.0 after downgrading to 25.10?

GRUB still listed the 26.04 kernel as the default. After hop one I rebooted into 7.0.0-27-generic while packages were already 25.10. Set GRUB_DEFAULT to a 6.17 or 6.14 image before hop two, or purge linux-image-7.0.0-27-generic.

5. How do I fix grub-mkconfig not found after downgrade?

Reinstall grub-common, grub2-common, and grub-pc-bin from the target suite, then run dpkg --force-confdef --force-confold --configure -a. My hop two failed grub-pc postinst until those packages were reinstalled.

6. Why does libc6 stay at 2.42 when /etc/os-release says 25.04?

coreutils-from-uutils on 25.04 pulls gnu-coreutils which PreDepends libc6 >= 2.42—a 25.10-era library. apt refused to downgrade libc6 to 2.41. The release file moved but the C library stayed hybrid.

7. What is the safest way to roll back Ubuntu 26.04?

Restore a VirtualBox snapshot taken before the upgrade. apt pinning is lab-only documentation, not a production rollback strategy.

8. Should I reboot between downgrade hops?

Yes. Clear /var/run/reboot-required, confirm uname -r matches a kernel that still exists in /boot, then start the next pin file and suite retarget. I rebooted between hop one and hop two on the test VM.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …