Upgrading Debian 12 to Debian 13 (trixie)
Upgrading Debian 12 to Debian 13 is usually not complicated if you already have a clean, fully mastered Debian 12 installation. In this note (which I use myself) we go through the main migration steps.
If you want to maximise stability a little further, I advise waiting for version 13.1, which comes out shortly after version 13.0, on a Saturday.
Every command is run as root, through the server's KVM console or over SSH. No pointless sudo, become root.
Why migrate to Debian 13 (without rushing)
Section titled “Why migrate to Debian 13 (without rushing)”You use a Debian server to host WordPress, for example.
WordPress needs PHP, and is built for the PHP version most used at the time. You therefore have to keep up with the releases, or you will be stuck on updates sooner or later.
Debian brings a performance improvement (new scheduler, http/3, and so on).
You will find more and more online documentation referring to Debian 13 and less and less to Debian 12. To be able to rely on it and stay in step, you have to follow. The same goes for those still resisting systemd in place of initrd.
What (bad) surprises are waiting for you
Section titled “What (bad) surprises are waiting for you”Abracadabra!
-
The
last,lastbandlastlogcommands are gone. Check your scripts if you use them. -
Critical stop of your MariaDB server, with no way to restart it: check that your MariaDB server starts correctly and without errors before upgrading Debian, because repair is impossible once the MariaDB version has changed.
-
If you have external (unofficial) repositories, expect them to be disabled, and your specific packages to be downgraded or removed.
1. Backups
Section titled “1. Backups”An upgrade can go wrong, destroy data, or leave the server unbootable.
I back up servers with BackupPC, RCLONE and snapshots (yes, all three). Databases must be dumped to SQL before any file backup.
Check that your system is properly backed up.
That the backups are held off site.
Take a snapshot as well if it is a virtual machine.
Set aside time to repair in case of trouble.
Be able to reboot in rescue mode.
2. Plain update of your Debian 12
Section titled “2. Plain update of your Debian 12”Your server is normally already up to date, since you are conscientious. If not, it absolutely has to be before you start:
apt updateapt upgradereboot # if needed3. Stop Puppet
Section titled “3. Stop Puppet”If you use Puppet, stop it. Its manifests will have to be reviewed for the new system version.
systemctl stop puppet4. Remove non-Debian packages
Section titled “4. Remove non-Debian packages”If you have installed unofficial packages, they have to go. You will put them back later, if they still work.
To find those packages, use these commands:
apt-get -s purge '?and(?installed,?not(?any-version(?origin(Debian))),?not(?name(puppet-agent)))'If the list of packages to purge looks right, apply it:
apt-get purge -y '?and(?installed,?not(?any-version(?origin(Debian))),?not(?name(puppet-agent)))'Remove the puppet package without purging it:
apt remove puppet-agent5. Remove obsolete packages
Section titled “5. Remove obsolete packages”An obsolete package is still installed but no longer exists in the repositories. Debian drops security support for it about a year after trixie's release.
Look at the list first:
apt list '?obsolete'Read it before purging: a package you installed yourself from an external source shows up here too.
apt purge '?obsolete'6. Remove leftover configuration files
Section titled “6. Remove leftover configuration files”Check which configuration sample files are to be deleted.
find /etc -name '*.dpkg-*' -o -name '*.ucf-*' -o -name '*.merge-error'Then delete them for real if everything looks fine:
find /etc \( -name '*.dpkg-*' -o -name '*.ucf-*' -o -name '*.merge-error' \) -type f -delete7. Disable APT pinning
Section titled “7. Disable APT pinning”Check the file or the directory /etc/apt/preferences or /etc/apt/preferences.d
They pin package versions. Check what needs doing, but these files most likely have to be disabled.
8. Check the package state
Section titled “8. Check the package state”No package may be left in an unfinished installation state or any other:
dpkg --audit9. Check for held packages
Section titled “9. Check for held packages”A held package is kept at its current version and refuses to move up. The list must be empty before the migration, otherwise the upgrade stops on a dependency conflict that is hard to read.
apt-mark showholdRelease the hold on whatever comes up, unless you have a precise reason to keep it:
apt-mark unhold <package>10. Update the sources.list files
Section titled “10. Update the sources.list files”In /etc/apt/sources.list or /etc/apt/sources.list.d/*, replace bookworm with trixie, and you should end up with:
deb http://deb.debian.org/debian trixie main contrib non-free non-free-firmwaredeb http://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmwaredeb http://security.debian.org trixie-security main contrib non-free non-free-firmwareIMPORTANT: the name to use is deb.debian.org, which automatically points to the nearest mirror.
Or move into the directory and replace bookworm with trixie in a single command:
sed -i 's/bookworm/trixie/g' *.listThe new deb822 format
Section titled “The new deb822 format”Debian 13 expects its sources in /etc/apt/sources.list.d/debian.sources, in deb822 format: one stanza per repository, one field per line. The historical one-line format still works, but a .sources file has no .list extension, so the sed command above leaves it untouched. Check that the directory holds none before concluding your sources are up to date.
The same repositories as above, in deb822:
/etc/apt/sources.list.d/debian.sources:
Types: debURIs: https://deb.debian.org/debianSuites: trixie trixie-updatesComponents: main contrib non-free non-free-firmwareSigned-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: debURIs: https://security.debian.org/debian-securitySuites: trixie-securityComponents: main contrib non-free non-free-firmwareSigned-By: /usr/share/keyrings/debian-archive-keyring.gpgA given repository must be declared only once. If you create this file, empty or delete the old /etc/apt/sources.list.
11. Update the list of available packages
Section titled “11. Update the list of available packages”apt update12. Check disk space before upgrading
Section titled “12. Check disk space before upgrading”apt -o APT::Get::Trivial-Only=true full-upgrade[ ... ]XXX upgraded, XXX newly installed, XXX to remove and XXX not upgraded.Need to get xx.xMB of archives.After this operation, AAAMB of additional disk space will be used.If there is not enough room, this message appears:
E: You don't have enough free space in /var/cache/apt/archives/.13. Cleanup
Section titled “13. Cleanup”apt cleanapt --purge autoremove14. Check the kernel metapackage
Section titled “14. Check the kernel metapackage”The kernel metapackage (linux-image-amd64 on a standard 64-bit server) automatically follows the kernel versions. Without it, the upgrade leaves the old kernel in place and the server reboots on it.
dpkg -l 'linux-image*' | grep ^ii | grep -i metaIf the command returns nothing, install the metapackage matching your architecture before upgrading:
apt install linux-image-amd6415. Open a detachable session
Section titled “15. Open a detachable session”The two commands that follow take a long time. Run straight from an SSH session, a network drop interrupts them mid-work and leaves the system half migrated. A screen or tmux session keeps running on the server even if your connection dies.
apt install tmuxtmux new -s upgradeAfter a drop, reconnect over SSH and take back control:
tmux attach -t upgradeFrom the KVM console this is not needed.
16. Minimal upgrade
Section titled “16. Minimal upgrade”This step upgrades the system packages that neither add new dependencies on new packages nor remove any:
DEBIAN_FRONTEND=noninteractive UCF_FORCE_CONFFOLD=1 NEEDRESTART_MODE=a apt -o Apt::Get::Assume-Yes=true -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade --without-new-pkgs17. Final upgrade
Section titled “17. Final upgrade”DEBIAN_FRONTEND=noninteractive UCF_FORCE_CONFFOLD=1 NEEDRESTART_MODE=a apt -o Apt::Get::Assume-Yes=true -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" full-upgradeapt --purge autoremoveIf all went well, reboot the system.
If anything went wrong, analyse the situation before rebooting.
