How to Downgrade Ubuntu 26.04 LTS to 25.04

Tested on Ubuntu 25.04 (Plucky Puffin)
Applies to Ubuntu
Privilege sudo or root
Scope Downgrade Ubuntu 26.04 LTS to 25.04, including pre-checks, migration steps, and post-upgrade verification.
Related guides Add Apt Repository Command Not Found
Apt Install Specific Version
Backup Brave Browser Session Ubuntu
Check Ubuntu Version
Configure Vnc Server Ubuntu

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.

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

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.

Check mount-point usage and filesystem types with df; the df and du covers -h, -T, and filtering pseudo-filesystems.

Cross-check /etc/os-release with check Ubuntu version when pinning or retargeting suites so apt points at the right codename.

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:

The example below uses dpkg on Debian-family systems; the dpkg command is a quick reference for install, list, and query options.

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:

output
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 experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)