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; kernel7.0.0-27-genericstill running after final hop.
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.
aptitudeinstalled.- 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.
cat /etc/os-release
uname -r
df -h /
sudo cp /etc/apt/sources.list.d/ubuntu.sources ~/ubuntu.sources.backupStarting point on my VM:
PRETTY_NAME="Ubuntu 26.04 LTS"
VERSION_CODENAME=resolute
6.17.0-40-genericHop 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:
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: 1003The 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.
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=falseHop 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:
E: Internal Error, AutoRemover broke stuffPython 3.14 overwrite conflict mid-run:
trying to overwrite '/usr/lib/python3.14/shutil.py', which is also in package libpython3.14-minimalgdm3 interactive prompt blocked apt -f install until I ran:
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:
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-minimalResult:
PRETTY_NAME="Ubuntu 25.10"
VERSION_CODENAME=questingFiles 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:
uname -r
7.0.0-27-genericThat 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.
cat /var/run/reboot-required || echo "OK"
cat /etc/os-release | grep PRETTYOK
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:
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:
/usr/sbin/update-grub: 3: exec: grub-mkconfig: not found
grub-mkdevicemap: command not foundFix:
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 -alibc6 stuck at 2.42 (25.10) while /etc/os-release already said 25.04:
apt-cache policy libc6Installed: 2.42-0ubuntu3.1
Candidate: 2.41-6ubuntu1.2Explicit downgrade refused:
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.
cat /etc/os-release
uname -r
dpkg -l libc6 base-files
dpkg --audit
ls /boot/vmlinuz-*
apt list '?obsolete'
do-release-upgrade -cFinal values on my VM:
PRETTY_NAME="Ubuntu 25.04"
VERSION_CODENAME=plucky
7.0.0-27-generic
libc6 2.42-0ubuntu3.1
base-files 13.6ubuntu2/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
- How to roll back Ubuntu to a previous version? (Ask Ubuntu)
- Clone or backup a Linux partition with fsarchiver
- Linux LVM snapshot backup and restore
- APT preferences manual
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.

