How to Upgrade a Server From Debian 10 (Buster) to Debian 12 (Bookworm)

Blog image

AI summary

Overview: This document outlines a complete procedure to migrate a server from Debian 10 to Debian 12 using the supported intermediate release. It covers pre-upgrade assessment, backup and rollback options, the two-stage upgrade process, major compatibility considerations, and the steps required to validate and stabilize the system after the migration.

Core message: The upgrade must be performed sequentially through the intermediate release, with comprehensive preparation, verified rollback mechanisms, and careful validation at each stage to avoid dependency conflicts, broken services, or unbootable systems.

Preparation and safeguards: Before changing releases, audit package state, held packages, third-party repositories, kernel modules, available disk space, and active services/ports. Ensure out-of-band console access and create reliable backups such as hypervisor or LVM snapshots and logical database dumps. Preserve critical configuration and system directories when snapshots are not available.

Staged upgrade approach: First bring the existing release fully up to date, disable external repositories, update package sources to the intermediate release, and perform a conservative then full upgrade while resolving configuration-file decisions manually. After validating the intermediate state, repeat the process to move to the target release, again handling prompts for bootloader, library, and service changes deliberately and during a maintenance window.

Compatibility and risk areas: Expect staged ABI and library transitions (C library, TLS library, Python, init system and others) that can break binaries, drivers, or integrations if jumped over. Third-party repos, DKMS-managed modules, container networking, and service unit changes commonly require attention, rebuilding, or configuration adjustments during the migration.

Post-upgrade validation and hardening: Reboot and confirm the new release and kernel, verify no failed units or package audit issues, remove obsolete packages, reconcile kernel images and modules, re-enable external repositories conservatively, re-run security baseline checks, and capture a final validated snapshot as the new rollback baseline.

How to Upgrade a Server From Debian 10 (Buster) to Debian 12 (Bookworm)

This guide covers the complete migration path from Debian 10 (Buster) to Debian 12 (Bookworm) via the mandatory intermediate release, Debian 11 (Bullseye). It addresses pre-upgrade auditing, backup and rollback architecture, the staged upgrade procedure, compatibility considerations for Bookworm, and post-upgrade verification.

1. Why You Cannot Skip Debian 11

The only supported upgrade path is sequential:

Debian 10 (Buster) → Debian 11 (Bullseye) → Debian 12 (Bookworm)

Skipping Bullseye creates nonlinearly growing dependency conflicts because core ABI transitions happen in stages.

Key reasons

  1. glibc 2.28 to 2.36
    A two-step ABI transition. Skipping intermediate compatibility shims causes runtime failures in packages compiled against older symbol versions.
  2. OpenSSL 1.1.1 to 3.0
    These are distinct major versions with incompatible API and ABI surfaces. A staged upgrade through Bullseye (which ships 1.1.1) allows identification of applications linked against libssl1.1 before Bookworm makes them blocking.
  3. Python 3.7 to 3.9 to 3.11
    Package namespace changes, removal of distutils, and PEP 668 pip restrictions accumulate across two releases and cannot be resolved in a single jump.
  4. systemd 241 to 252
    Sandboxing defaults tightened, deprecated unit directives removed. Services with custom unit files need intermediate validation on Bullseye.
  5. Package renames and splits
    iptables/nftables integration, python-is-python3, libpcre2/libpcre3, and non-free-firmware separation. APT cannot resolve these transitions in one step.

2. Pre-Upgrade Planning

2.1 Common Failure Modes

Understanding these categories prevents the majority of upgrade failures.

Failure CategoryDescriptionMitigation
Third-party reposDocker, Kubernetes, Elastic, MongoDB repos are release-specific; will 404 or conflict after the switchDisable before upgrading; re-enable after
DKMS modulesZFS, NVIDIA, WireGuard tied to specific kernel ABI; break on new kernel installVerify vendor support for target kernel
Held packagesapt-mark hold prevents upgrades; creates deadlocks if core libs are heldReview and unhold before starting
PHP version conflictsondrej/php and debian.org PHP packages conflict after dist-upgradeDisable sury.org repo before Stage 1
Database major versionsMariaDB 10.3 → 10.5 → 10.11; PostgreSQL independent; MySQL absent from BookwormTake logical dumps; validate engine compatibility
Insufficient disk spaceAPT unpacks before removing; 2–4 GB needed in /var and /usrEnsure 4 GB free before each stage
conffile divergenceModified config files prompt for resolution; silent defaults can overwrite customizationsReview diffs; never use -y blindly

2.2 Pre-Upgrade Audit Commands

# Check for broken package states

dpkg –audit

dpkg –configure -a && apt –fix-broken install

# List held packages

apt-mark showhold

# Inventory all active repositories

grep -rh “^deb” /etc/apt/sources.list /etc/apt/sources.list.d/ | sort | uniq

# Check available disk space

df -h

# Identify DKMS modules

dkms status

# Save baseline for post-upgrade comparison

systemctl list-units –type=service –state=active > /root/services-before.txt

ss -tulpn > /root/ports-before.txt

3. Backup and Rollback Architecture

Never commence a Debian upgrade without a verified, tested rollback path. An upgrade that breaks the bootloader or produces an unbootable system is only recoverable via out-of-band access.

Verify IPMI, iDRAC, or iLO console access before beginning. Attempting a major distribution upgrade over SSH without console fallback is an unacceptable operational risk.

3.1 Hypervisor Snapshots (Preferred)

For KVM, VMware, or Proxmox, a consistent snapshot taken immediately before any repository modification is the fastest and most reliable rollback mechanism.

virsh snapshot-create-as –domain myvm \

  –name “pre-debian11-$(date +%Y%m%d)” \

  –atomic

3.2 LVM Snapshots

Ensure 15–25% free space in the volume group before creating a snapshot, as the snapshot grows with writes during the upgrade.

lvcreate -L20G -s -n root_snap_prebullseye /dev/mapper/vg0-root

# To roll back:

systemctl isolate rescue.target

lvconvert –merge /dev/vg0/root_snap_prebullseye && reboot

3.3 Database Logical Dumps

Always take logical (SQL) dumps rather than binary file copies. Major version upgrades can change on-disk storage formats.

# MySQL / MariaDB

mysqldump –all-databases –single-transaction –routines \

  –triggers –events > /backup/all_dbs_$(date +%Y%m%d).sql

# PostgreSQL

pg_dumpall -U postgres > /backup/postgres_all_$(date +%Y%m%d).sql

3.4 Critical Directories (When Snapshots Are Unavailable)

DirectoryContentsPriority
/etcAll system configurationsCritical
/var/lib/dpkgPackage databaseCritical
/bootKernel, initrd, GRUB configCritical
/var/lib/mysql or /var/lib/postgresqlDatabase files (prefer logical dump)Critical
/var/wwwWeb contentHigh
/opt, /srvThird-party apps, service dataMedium

4. Stage 1: Debian 10 to Debian 11 (Bullseye)

4.1 Fully Update Debian 10 First

The upgrade must start from a fully current Buster installation. Upgrading from a system with accumulated pending updates compounds the dependency resolution problem.

apt update && apt upgrade && apt full-upgrade

apt autoremove –purge && apt autoclean

reboot

# Confirm the latest point release (should be 10.13)

lsb_release -a && cat /etc/debian_version

4.2 Disable Third-Party Repositories

for f in /etc/apt/sources.list.d/*.list; do

  mv “$f” “${f}.disabled”

done

4.3 Update sources.list

Replace all instances of buster with bullseye:

deb http://deb.debian.org/debian bullseye main contrib non-free

deb http://security.debian.org/debian-security bullseye-security main contrib non-free

deb http://deb.debian.org/debian bullseye-updates main contrib non-free

apt update

Verify no 404 or GPG errors before proceeding.

4.4 Perform the Upgrade

# Phase 1: in-place replacements only

apt upgrade –without-new-pkgs

# Phase 2: full dependency resolution

apt full-upgrade

When APT prompts about modified configuration files:

  • Press D to view the diff.
  • Keep your version (N) for customized files, such as:
    • sshd_config
    • nginx.conf
    • php.ini
  • Accept the maintainer version (Y) for files you have not changed.

Never use -y or DEBIAN_FRONTEND=noninteractive without a reviewed conffile policy.

If APT reports that critical packages (database engine, web server, VPN daemon) need to be removed, stop and investigate before proceeding.

4.5 Post-Bullseye Validation

reboot

lsb_release -a

uname -r

dpkg –audit

systemctl –failed –no-pager

journalctl -p err -b –no-pager | head -50

diff /root/ports-before.txt <(ss -tulpn)

# Cleanup

apt autoremove –purge

dpkg -l | grep ‘^rc’ | awk ‘{print $2}’ | xargs apt purge -y

apt clean

Expected:

  • Debian 11
  • Kernel 5.10.x
  • No failed units
  • No package audit errors

4.6 Bullseye Compatibility Notes

iptables/nftables
Debian 11 defaults to iptables-nft.
update-alternatives –display iptables

  1. PHP
    Bullseye ships PHP 7.4. Test applications that relied on PHP 7.3 behavior.
  2. Python
    python3 now resolves to 3.9. Validate virtual environments and library dependencies.
  3. OpenSSL
    Still 1.1.1 in Bullseye. The 3.0 transition comes in Stage 2.

5. Stage 2: Debian 11 to Debian 12 (Bookworm)

Do not begin Stage 2 until:

  • dpkg –audit returns no output
  • systemctl –failed shows nothing
  • all critical services are operational
  • a fresh Bullseye snapshot exists

5.1 Disable Third-Party Repositories Again

for f in /etc/apt/sources.list.d/*.list; do

  mv “$f” “${f}.disabled”

done

5.2 Update sources.list for Bookworm

deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware

deb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware

deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware

timedatectl status

apt update

5.3 Perform the Upgrade

apt upgrade –without-new-pkgs

apt full-upgrade

5.4 Bookworm-Specific Upgrade Prompts

GRUB on software RAID grub-install /dev/sda && grub-install /dev/sdb && update-grub

OpenSSL 3 transition

find /usr/bin /usr/sbin /usr/local/bin -type f -executable \

  -exec ldd {} 2>/dev/null \; | grep libssl1.1 | sort | uniq

SSH reconfiguration. Bookworm deprecates RSA keys below 2048 bits and removes some legacy cipher suites.

Service restarts. Prefer manually controlling restart timing during maintenance windows.

5.5 Post-Bookworm Validation

reboot

lsb_release -a && cat /etc/debian_version

uname -r

dpkg –audit

systemctl –failed –no-pager

journalctl -p err -b –no-pager | head -100

# Find obsolete packages

aptitude search ‘~o’

# Cleanup

apt autoremove –purge

dpkg -l | grep ‘^rc’ | awk ‘{print $2}’ | xargs apt purge -y

apt clean

Expected:

  • Debian 12.x
  • Kernel 6.1.x
  • No failed services
  • No audit errors

6. Bookworm Compatibility Reference

6.1 OpenSSL 3.0

OpenSSL 3.0 introduced substantial compatibility changes.

Legacy provider configuration

[openssl_init]

providers = provider_sect

[provider_sect]

default = default_sect

legacy = legacy_sect

[default_sect]

activate = 1

[legacy_sect]

activate = 1

Additional notes

  • ENGINE API deprecated
  • HSM integrations may fail until updated
  • Self-signed certificates require:
    • subjectAltName
    • keyUsage
    • extendedKeyUsage

6.2 PHP 8.2

Removed functionality

  • create_function()
  • each()
  • Dynamic properties without #[AllowDynamicProperties]

Other changes

  • mbstring.func_overload removed
  • @ no longer suppresses fatal errors
  • Type coercion behavior changed significantly

6.3 Python 3.11

  1. PEP 668 blocks system-wide pip install
  2. distutils deprecated
  3. asyncio event loop defaults changed

6.4 nftables and Container Networking

nft list ruleset

iptables-legacy -L -n

docker network inspect bridge

docker run –rm alpine ping -c 2 8.8.8.8

Validate:

  • Docker networking
  • Kubernetes kube-proxy
  • Calico
  • Flannel

6.5 Re-enabling Docker After Bookworm

echo “deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] \

  https://download.docker.com/linux/debian bookworm stable” \

  > /etc/apt/sources.list.d/docker.list

apt update

apt install docker-ce docker-ce-cli containerd.io \

  docker-buildx-plugin docker-compose-plugin

docker info && docker run –rm hello-world

6.6 Kubernetes Nodes

# Before upgrade

kubectl drain <node-name> –ignore-daemonsets –delete-emptydir-data

# After upgrade

kubectl uncordon <node-name>

kubectl get nodes

kubectl describe node <node-name>

7. Final Cleanup and Hardening

7.1 Kernel Cleanup

dpkg -l | grep linux-image

uname -r

apt purge linux-image-5.10.x-x-amd64

update-grub

7.2 Security Baseline Verification

# SSH hardening

sshd -T | grep -E ‘permitrootlogin|passwordauthentication|pubkeyauthentication’

# Firewall

nft list ruleset | head -30

# PAM

pam-auth-update –status

# World-writable files

find /etc /usr/bin /usr/sbin -perm -002 -type f 2>/dev/null

7.3 Re-enabling Third-Party Repositories

mv /etc/apt/sources.list.d/docker.list.disabled \

   /etc/apt/sources.list.d/docker.list

apt update

apt –dry-run upgrade

7.4 Final Snapshot

After completing all validation, take a snapshot or backup of the clean Bookworm system. This becomes the new rollback baseline and serves as evidence of the post-upgrade state for change management purposes.

Can I upgrade directly from Debian 10 to Debian 12?

The only supported path is:

Debian 10 (Buster) → Debian 11 (Bullseye) → Debian 12 (Bookworm)

Skipping Debian 11 can break package dependency resolution, OpenSSL transitions, Python runtime compatibility, and system libraries such as glibc.

How long does the upgrade usually take?

System Type Estimated Time
Small VM 30–60 minutes
Production web server 1–2 hours
Database server 2–4 hours
Kubernetes node Depends on the workload evacuation time

Is it safe to upgrade over SSH?

Only if you have verified out-of-band console access, such as:

  • IPMI
  • iDRAC
  • iLO
  • Hypervisor console access

A failed kernel, GRUB issue, or networking problem can permanently disconnect SSH access during the upgrade.

Should I use apt upgrade or apt full-upgrade?

Both are required.

apt upgrade –without-new-pkgs

apt full-upgrade

Why must third-party repositories be disabled first?

Third-party repositories are usually release-specific and can introduce:

  • dependency conflicts
  • broken package chains
  • outdated signing keys
  • incompatible package versions

Disable them before each stage and re-enable them individually afterward.

How much free disk space is required?

Mount Point Recommended Free Space
/ 4 GB
/var 2–4 GB
/boot Space for multiple kernels/initramfs images

Do I need to reboot between upgrade stages?

Yes. Reboot after:

  1. Debian 10 → Debian 11
  2. Debian 11 → Debian 12

This ensures the new kernel, libraries, and services load correctly.

Related articles

1How to Create an LVM Partition in Linux

How to Create an LVM Partition in Linux

 Learn how to create an LVM partition in Linux using industry-standard tools and best practices for modern server environments. This step-by-step guide covers physical volumes, volume groups, logical volumes, filesystem creation, mounting, live storage expansion, and advanced LVM management techniques for Ubuntu, RHEL, VPS, and enterprise Linux systems. Whether you are deploying scalable storage for […]
1How to Change the SSH Port

How to Change the SSH Port

Learn how to change the default SSH port on Linux safely without locking yourself out. This expert guide covers Ubuntu, Debian, Rocky Linux, AlmaLinux, firewalls, SELinux, and modern systemd socket activation, including Ubuntu 24.04 and Debian 13 configurations. Includes troubleshooting tips, security hardening recommendations, and real-world examples for production servers. How to Change the SSH […]
1How to Fix the “nf_conntrack: table full” Error on Linux Servers

How to Fix the “nf_conntrack: table full” Error on Linux Servers

Experiencing nf_conntrack: table full, dropping packet errors? This expert guide explains how Linux connection tracking works, why conntrack tables overflow, and how to optimize Netfilter for high-traffic environments.  How to Fix the “nf_conntrack: table full” Error on Linux Servers When a Linux server begins logging messages such as: nf_conntrack: table full, dropping packet It indicates […]
1Digital Rights Management for Video Streaming Platforms

Digital Rights Management for Video Streaming Platforms

Digital Rights Management is often treated as a security checkbox: enable DRM, protect content, move on. In real-world video streaming, that assumption breaks quickly. DRM sits directly on the playback path, affects startup time, scales with concurrency, and fails in ways that look like video delivery problems, not security issues.
1How to Provision a Server Properly | Step-by-Step Infrastructure Guide

How to Provision a Server Properly | Step-by-Step Infrastructure Guide

Provisioning a server is often treated as a quick, automated step: click order, wait for Active, and move on. In reality, most infrastructure problems begin right there, when provisioning is mistaken for readiness.
1How to Point a Domain to a Dedicated Server IP (Step-by-Step)

How to Point a Domain to a Dedicated Server IP (Step-by-Step)

How to Point Your Domain Name to a Dedicated Server’s IP Address? Before changing any DNS records, it’s important to clearly understand what problem you are solving.At Advanced Hosting, most DNS-related incidents we see are caused not by mistakes in records, but by incorrect expectations about what DNS is supposed to do. This article removes […]