Every two years a new major linux debian version is released, causing users and administrators to consider upgrading their systems. While a fresh install is the cleanest option, upgrading from one major release to the next isn't actually as scary as many think. This article shows how to upgrade from debian 12 "bookworm" to debian 13 "trixie", but the steps (except for one we point out specifically) apply to any other major release upgrade as well.
Preparing the system
Before upgrading the debian version itself, you should ensure that it is as up to date as possible:
sudo apt update
sudo apt upgrade
sudo apt full-upgrade
Once done, remove packages that are no longer needed and clear the package cache:
sudo apt autoremove --purge -y
sudo apt clean
Finally, reboot your system:
sudo reboot
The rebooting step isn't strictly necessary, but it helps catch preexisting configuration errors that may otherwise be carried over into the upgrade process, potentially leaving the system in an unusable state.
Preventing upgrade errors
The vast majority of upgrade issues stem from two root causes: package conflicts and interrupted upgrades. These problems can largely be prevented by making sure the system is in an acceptable state before performing the upgrade.
First, make sure you have no broken, partially installed or held packages:
sudo apt-get check
sudo dpkg --audit
sudo apt-mark showhold
If any of the above commands produces output, you will need to resolve those first as they will likely conflict with the upgrade process.
Another tool that may conflict with package operations is unattended-upgrades
, which you should temporarily mask until the upgrade is done (if installed):
sudo systemctl stop unattended-upgrades.service
sudo systemctl mask unattended-upgrades.service
In order to prevent interruptions due to resource constraints, ensure your partitions in /var
and /usr
have enough free space to store the new packages:
df -h
If either /var
or /usr
have less than 5gb of space, upgrading to a new major release may be risky; consider freeing up some space before you continue.
Next, check your free memory
free -mh
If you have less than 1GiB of memory available (see "available" column, not "free!), consider stopping some background services or containers to temporarily have enough resources for the upgrade.
The above steps significantly reduce the chances of getting stuck with a partial upgrade, but some things can't be planned for reliably (power loss, hardware failure etc). In order to safely upgrade despite these remaining risks, consider backing up your environment, specifically /var
, /usr
, /etc
and /home
. In the unlikely case your debian installation breaks during the upgrade, you cant simply boot from a live usb/disk and replace these directories with your backed up versions, reboot and have a working machine again.
Upgrading the system
With the host prepared and desaster recovery in place, it is time to run the actual upgrade.
The first step is to replace the codename of the current release with the codename of the target release in the .list
and .sources
files in /etc/apt/
.
In this example, we are upgrading from debian 12 (codename bookworm
) to debian 13 (codename trixie
). If you want to upgrade between different versions, simply find their hostnames on the debian releases page and replace them in the following command.
find /etc/apt -iregex '.*\.\(list\|sources\)$' -exec sudo sed -i 's/bookworm/trixie/g' {} \;
This is the only command you need to adjust if you are upgrading from/to a different debian version. When upgrading, make sure to only upgrade one major version at a time and don't jump between release channels (eg don't upgrade from testing to stable).
With the new sources configured, update the package index:
sudo apt update
Then start by performing a minimal upgrade (essential packages only):
sudo apt upgrade --without-new-pkgs -y
Next, perform a full distribution upgrade to allow installing all remaining packages:
sudo apt full-upgrade -y
And fix any arising dependency issues or broken packages:
sudo dpkg --configure -a
sudo apt --fix-broken install -y
Finally, install the new release's kernel and update the boot configuration:
sudo apt install linux-image-amd64 linux-headers-amd64 -y
sudo update-grub
sudo update-initramfs -u -k all
And that's it! If you haven't experienced any errors until now, your system completed the major version upgrade.
Validating the new environment
Even if the upgrade process seems to have been successful, always make sure to validate the new system before assuming ti is fully operational.
Start by making sure these commands correctly print the new version and codename:
cat /etc/debian_version
lsb_release -a
Next, check if there are any newly broken or held packages after the upgrade:
sudo dpkg --audit
sudo apt-get check
sudo apt-mark showhold
If any of these commands produce output, you should resolve those issues before continuing.
Finally, check if any services have experienced failures:
sudo systemctl --failed
If no services are listed then your system seems operational. If you want to be extra sure, consider rebooting again.
Cleaning up after the upgrade
A major version upgrade may leave more remnants than normal package upgrades, which should be cleaned immediately after the upgrade process is done to save space and prevent later errors.
Remove packages not needed by the new system anymore and clear the apt package cache:
sudo apt autoremove --purge -y
sudo apt clean
Upgrading may leave some dangling library packages (not programs!) that are "orphaned", as in not needed anymore but not marked as "automatically installed", so apt autoremove
won't touch them. You can find these orphaned packages using the deborphan
tool, which is not installed by default:
sudo apt install deborphan
Running the tool will print the names of all library packages that no other packages depend on:
sudo deborphan
You should look through this list and remove any libraries you don't need anymore. Note that after removing them, deborphan
may find further orphaned packages, so you likely need to run it multiple times to catch them all. If you didn't manually install libraries (eg to build packages from source), you can simply remove everything deborphan
finds in a loop until nothing is found:
while deborphan | grep .; do deborphan | tee -a ~/deborphan-removed.log | xargs sudo apt -y remove --purge; done
This script creates a safeguard file deborphan-removed.log
, which contains the names of all packages that were removed by the loop. If you experience issues after removal, simply run xargs sudo apt install -y < ~/deborphan-removed.log
to undo the procedure.
Finally, if you had unattended-upgrades
installed and want it reenabled, undo the masking steps from the beginning:
sudo systemctl unmask unattended-upgrades.service
sudo systemctl start unattended-upgrades.service
You are now done with the entire upgrade process. Don't forget to delete the backups you took earlier or move them to cold storage.