A Debian release upgrade replaces the package set behind the installed system, so the risky point is not only the apt full-upgrade command. The upgrade needs a tested backup, recovery access, consistent APT sources, and a post-reboot check that the system is running the target release instead of a half-upgraded mix.

Debian supports release upgrades one stable release at a time. For the current stable path, upgrade Debian 12 bookworm to Debian 13 trixie after bringing Bookworm fully up to date; systems on older releases should first follow the release notes for each intermediate version.

APT should point at codenames such as bookworm and trixie during the change, not moving names such as stable or oldstable. Third-party repositories, sloppy backports, package holds, and APT pinning can pull the resolver away from the target release, so remove or disable them before changing the Debian archive entries.

Steps to upgrade Debian to a newer release:

  1. Confirm the current Debian release before changing package sources.
    $ cat /etc/debian_version
    12.14

    Debian supports the direct release upgrade from the previous stable release to the new stable release. For example, upgrade bookworm to trixie before planning any later release jump.

  2. Confirm that the system has a restorable backup and a recovery path outside the upgraded operating system.

    A failed reboot can require console, hypervisor, serial, installer rescue, or live-media access. Do not start a remote release upgrade when SSH is the only recovery path.

  3. Keep a package selection record with the backup.
    $ dpkg --get-selections '*' > ~/debian-package-selections.txt
  4. Save the current APT configuration before editing release sources.
    $ sudo cp -a /etc/apt /root/apt-before-release-upgrade
  5. Refresh the current release package index.
    $ sudo apt update
    Hit:1 http://deb.debian.org/debian bookworm InRelease
    Hit:2 http://deb.debian.org/debian bookworm-updates InRelease
    Hit:3 http://deb.debian.org/debian-security bookworm-security InRelease
    Reading package lists... Done
    All packages are up to date.
  6. Bring the current release fully up to date before switching codenames.
    $ sudo apt full-upgrade
    Reading package lists... Done
    Building dependency tree... Done
    Calculating upgrade... Done
    0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

    Reboot here if the current-release upgrade installs a new kernel or low-level system package and the system has not already booted into that update.

  7. Ensure APT has the current Debian archive keyring and certificate store.
    $ sudo apt install ca-certificates debian-archive-keyring
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    debian-archive-keyring is already the newest version.
    ca-certificates is already the newest version.

    The official Debian release notes use HTTPS archive entries. Minimal systems without ca-certificates can fail certificate verification after switching to the target release sources.

  8. Check for broken package states before editing sources.
    $ dpkg --audit

    No output means dpkg found no half-installed or failed-configuration packages.

  9. Check for held packages and resolve any hold that should not block the release upgrade.
    $ apt-mark showhold

    No output means no packages are held by apt-mark. Related: How to hold a Debian package

  10. Replace the Debian archive entries with target-release Deb822 sources.
    $ sudoedit /etc/apt/sources.list.d/debian.sources
    Types: deb
    URIs: https://deb.debian.org/debian
    Suites: trixie trixie-updates
    Components: main non-free-firmware
    Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
     
    Types: deb
    URIs: https://security.debian.org/debian-security
    Suites: trixie-security
    Components: main non-free-firmware
    Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

    Keep contrib or non-free in the Components lines only when the system already uses those components. Disable old bookworm, bookworm-backports, proposed-updates, and unsupported third-party entries instead of mixing releases. Related: How to remove an APT repository on Debian

  11. Refresh APT metadata from the target release.
    $ sudo apt update
    Get:1 https://deb.debian.org/debian trixie InRelease [140 kB]
    Get:2 https://deb.debian.org/debian trixie-updates InRelease [47.3 kB]
    Get:3 https://security.debian.org/debian-security trixie-security InRelease [43.4 kB]
    Reading package lists... Done
    83 packages can be upgraded. Run 'apt list --upgradable' to see them.

    If this step reports certificate, signature, mixed-suite, or missing-release errors, stop and fix the source files before running any upgrade command.

  12. Run the minimal upgrade phase.
    $ sudo apt upgrade --without-new-pkgs
    Reading package lists... Done
    Building dependency tree... Done
    Calculating upgrade... Done
    The following packages have been kept back:
      adduser apt coreutils e2fsprogs
    ##### snipped #####
    The following packages will be upgraded:
      base-files base-passwd bash bsdutils
    ##### snipped #####
    67 upgraded, 0 newly installed, 0 to remove and 16 not upgraded.
    Do you want to continue? [Y/n]

    The minimal phase upgrades packages that do not need new package installs or removals. Held-back packages are expected here and are resolved by the full upgrade phase.

  13. Run the full release upgrade and review any removals before accepting.
    $ sudo apt full-upgrade
    Reading package lists... Done
    Building dependency tree... Done
    Calculating upgrade... Done
    The following packages will be REMOVED:
      libdb5.3 libext2fs2 libhogweed6 libnettle8 libssl3
    The following NEW packages will be installed:
      libdb5.3t64 libext2fs2t64 libhogweed6t64 libnettle8t64 libssl3t64
    The following packages will be upgraded:
      apt base-files bash dpkg libc6
    ##### snipped #####
    83 upgraded, 14 newly installed, 5 to remove and 0 not upgraded.
    Do you want to continue? [Y/n]

    Do not accept removals that would delete required local services, drivers, kernels, or vendor packages until the release notes or the package owner confirms the replacement path.

  14. Reboot into the upgraded system.
    $ sudo reboot
  15. Confirm the upgraded Debian release after reconnecting.
    $ cat /etc/debian_version
    13.5
  16. Refresh APT metadata again to confirm the post-upgrade sources work.
    $ sudo apt update
    Hit:1 https://deb.debian.org/debian trixie InRelease
    Hit:2 https://deb.debian.org/debian trixie-updates InRelease
    Hit:3 https://security.debian.org/debian-security trixie-security InRelease
    Reading package lists... Done
    All packages are up to date.
  17. Review packages that APT no longer needs before removing them.
    $ sudo apt autoremove
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    The following packages will be REMOVED:
      usr-is-merged
    0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
    Do you want to continue? [Y/n]

    Review the package list before confirming. Related: How to clean up disk space on Debian

  18. Check for obsolete or locally created packages that still need an owner decision.
    $ apt list '?obsolete'
    Listing... Done

    An empty list means APT did not find installed packages outside the enabled repositories. Investigate any listed package before purging it.