Debian releases a new stable version roughly every 2 years. Upgrading between versions is a routine procedure that goes through without trouble when prepared properly.
Current Debian Versions
| Code name | Version | Support |
|---|---|---|
| Bookworm | Debian 12 | Until 2028 |
| Bullseye | Debian 11 | Until 2026 (LTS) |
| Buster | Debian 10 | Support ended |
Step 1: Preparing the System
# Fully update the current version
sudo apt update
sudo apt full-upgrade -y
sudo apt autoremove -y
# Back up the list of installed packages
dpkg --get-selections > ~/installed-packages.txt
# Check free disk space (at least 5 GB is needed)
df -h /
Step 2: Update the Package Sources
# Replace bullseye with bookworm in sources.list
sudo sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list
sudo sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list.d/*.list
# Check the result
cat /etc/apt/sources.list
Step 3: The Upgrade (run it inside screen!)
sudo screen -S debian-upgrade
sudo apt update
sudo apt upgrade --without-new-pkgs -y
sudo apt full-upgrade -y
# Once it finishes — reboot
sudo reboot
Step 4: Verification After the Upgrade
# Debian version
cat /etc/debian_version
lsb_release -a
# Kernel version
uname -r
# Check the services
sudo systemctl status nginx
sudo systemctl status mysql
apt remove), complete the upgrade, then install them again from the new repository.Diagnosing common upgrade errors
The error "E: Unmet dependencies" during apt full-upgrade means some packages from the old release conflict with versions from the new one, and apt cannot work out the upgrade order automatically.
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).
The following packages have unmet dependencies:
php8.1-fpm : Depends: php8.1-common (= 8.1.2-1) but 8.2.7-1 is to be installed
The most common cause is a third-party PPA (for example ondrej/php) that has not yet updated its packages for the new release. Temporarily disable such repositories (sudo mv /etc/apt/sources.list.d/name.list /root/), finish the system upgrade, then restore the repository and update it separately.
A service fails to start after reboot with "Failed to start" — this usually means the config file uses syntax removed in the new package version.
systemctl status nginx
● nginx.service - A high performance web server
Active: failed (Result: exit-code)
Sep 30 12:00:01 server nginx[1234]: nginx: [emerg] unknown directive "ssl_stapling_file"
Check the package changelog (apt changelog nginx) — new versions periodically drop deprecated directives. Fix the config and run nginx -t before starting the service again.
Release upgrade methods compared
| Method | How it works | Risk | When to use it |
|---|---|---|---|
| Manual sources.list edit | sed + apt full-upgrade | Moderate, requires care | Headless servers, production |
| do-release-upgrade | Official Ubuntu script (not for Debian) | Low, has auto-rollback | Ubuntu Desktop/Server |
| New server plus data migration | Deployed from scratch, data moved over | Minimal for the system, costs migration time | Critical production with no allowed downtime |
When an in-place upgrade is not the right call
- The server holds critical production with no room for downtime — the risk of ending up with a broken system after full-upgrade outweighs the time saved. Deploy a new server and migrate the data instead.
- Many third-party PPAs and non-standard packages are in use — the chance of version conflicts grows with every extra repository.
- There is no current backup — jumping two versions ahead (for example Buster to Bookworm without the intermediate Bullseye) is not officially supported and can break the system with no way back.
Verifying the result
- Confirm the version matches what you expect:
cat /etc/debian_versionmust show the new stable release number. - Check that key services are running:
systemctl is-active nginx mysql php8.2-fpm— each must returnactive. - Check the journal for errors that appeared after reboot:
journalctl -p err -b— there should be no critical entries. - Open the site in a browser and check key functions — a major upgrade of the database (MariaDB) sometimes needs a separate
mysql_upgradestep.
It is worth checking and, if needed, updating the kernel separately — see the article on updating the Linux kernel. If the server runs Ubuntu rather than Debian, the process differs — see updating Ubuntu.