6. Upgrading Debian to the newest version

by Double Bastion - Updated August 16, 2023

If you already have Debian 12 (bookworm) installed on your server, skip to the next chapter.

Follow the steps from below to upgrade Debian 11 (bullseye) to Debian 12 (bookworm) if you either need to run the upgrade as part of your server’s maintenance, or you have just rented a server with Debian 11 installed, and the hosting company doesn’t offer servers with Debian 12 preinstalled.

First read the official upgrade documentation and take note, if what is described there is applicable to your situation.

As an additional precaution, open the default ssh port 22 in the firewall with UFW:

ufw allow 22

It’s important that you make sure you have a second way of accessing your server besides SSH, in case you loose SSH access to the server due to unexpected network issues that can happen during upgrade. Some hosting providers offer a web console that allows accessing the server without SSH, while other hosting companies offer a rescue mode boot up which you can use to log in to a different functional server and from there you can mount the hard drive of your disfunctional server, so that you can edit any files; then you can restart the server to apply the new changes.

6.1. Back up all the important data

Make a backup copy of all the important data stored on the server. For example, you should create compressed archives of the following directories: /var/www , /etc , /var/vmail , /var/lib/mysql , /var/lib/dpkg , /srv/scripts , /var/lib/asterisk , /var/spool/asterisk. It’s also recommended to make a backup copy of the /var/lib/apt/extended_states file and to save the output of the dpkg --get-selections "*" command. Also, you will want to make backup copies of all the SQL databases of your websites and applications.

Save all the backups in a safe location, like on an external hard drive that only you can access, adding the date of the backup to the name of the folder in which you store them.

6.2. Check the sources.list file

You will have to install all the available “bullseye” updates before upgrading to “bookworm”. On some systems, the package source is defined as “stable” in the sources.list file instead of “bullseye” or “bookworm”. To avoid an accidential early upgrade to “bookworm”, check the sources.list and ensure that it contains “bullseye” and not “stable” as source:

Open the /etc/apt/sources.list file:

nano /etc/apt/sources.list

The content should look like this:

deb http://deb.debian.org/debian bullseye main
deb-src http://deb.debian.org/debian bullseye main

deb http://deb.debian.org/debian-security/ bullseye-security main
deb-src http://deb.debian.org/debian-security/ bullseye-security main

deb http://deb.debian.org/debian bullseye-updates main
deb-src http://deb.debian.org/debian bullseye-updates main

Next, upgrade all “bullseye” packages to prepare the system for the final upgrade to “bookworm”.

Update the sources database:

apt-get update

Perform the first upgrade:

apt-get upgrade

Then run:

apt-get dist-upgrade

6.3. Check the state of installed packages to ensure that no packages are ‘on hold’ or with any error status

This test is important. You have to check the state of the installed packages to ensure that no packages are ‘on hold’ or with a status of ‘Half-Installed’ or ‘Failed-Config’ or with any error status. Your system and the apt database must be in good standing before proceeding with the upgrade. If there are any ‘on hold’ or broken packages, you should fix these problems before the upgrade. In the case of an ‘on hold’ package, you can ‘unhold’ it with the apt-mark unhold package-name command, then upgrade it with apt-get install package-name, and then, after the operating system upgrade, you can mark it as ‘on hold’ again with apt-mark hold package-name, to exclude it from being upgraded automatically during routine bulk software upgrades.

Check if any packages are ‘on hold’ with:

dpkg --get-selections | grep hold

Check if there are any packages with a status of ‘Half-Installed’, ‘Failed-Config’ or any error status, by running:

dpkg --audit

If both commands don’t return any packages, you can proceed with the upgrade.

6.4. Update the /etc/apt/sources.list file for “bookworm”

Edit the /etc/apt/sources.list file again:

nano /etc/apt/sources.list

Replace its content with the following lines:

deb http://deb.debian.org/debian bookworm main
deb-src http://deb.debian.org/debian bookworm main

deb http://deb.debian.org/debian-security/ bookworm-security main
deb-src http://deb.debian.org/debian-security/ bookworm-security main

deb http://deb.debian.org/debian bookworm-updates main
deb-src http://deb.debian.org/debian bookworm-updates main

Then run the following command to update the sources database:

apt-get update

6.5. Upgrade to Debian 12 (bookworm) in two steps

It is recommended to do the upgrade in two steps, by first running apt upgrade --without-new-pkgs to upgrade only the packages that can be upgraded without requiring any other packages to be removed or installed, then running apt full-upgrade to do the actual distribution upgrade.

First run:

apt upgrade --without-new-pkgs

Then perform the distribution upgrade by running:

apt full-upgrade

During the upgrade process you will be asked if you want the services that need restarting to be automatically restarted. You can answer yes to that question. You will also be asked multiple times if you want to overwrite certain configuration files, such as /etc/nginx/nginx.conf, with the new versions, or to keep the current files. Each time, type N and press Enter to keep the current configuration file, since you don’t want to loose the settings stored in that file.

Note: If, after the upgrade, you run systemctl --failed and notice that haveged, clamav-milter and clamav-clamonacc are in failed state, first disable clamav-clamonacc, because it is not needed:

systemctl disable clamav-clamonacc

Next, restart clamav-milter and haveged:

systemctl restart clamav-milter
systemctl restart haveged

A reboot will be required to finish the upgrade and load the new kernel:


6.6. Post-upgrade steps

To check which Debian version is currently installed on the system, take a look at the /etc/os-release file:

cat /etc/os-release

The output should look like this:

PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION="12 (bookworm)"

After you make sure that you can log in using SSH on your custom SSH port, you can close port 22 in the firewall with UFW:

ufw delete allow 22

Also, to remove all the packages that were automatically installed and are no longer required after upgrade, run:

apt autoremove

The obsolete python2.7, python3.7, python3.9 and perl-modules-5.28 packages can be also removed:

apt-get purge python2.7* python3.7* python3.9* perl-modules-5.28
apt autoremove

In Debian 12 rsyslog no longer creates some log files. Everything that used to be written to these files will still be logged in /var/log/syslog. Therefore, it’s safe to delete the following files, like this:

cd /var/log
rm mail.info*
rm mail.warn*
rm mail.err*
rm messages*
rm debug*
rm daemon.log*
rm php7.4-fpm.log*

The messages that were written to /var/log/mail.info, /var/log/mail.warn and /var/log/mail.err will be also available in /var/log/mail.log.

It’s also safe to delete the following leftover configuration files:

rm /etc/cron.daily/bsdmainutils.dpkg-remove
rm /etc/ca-certificates.conf.dpkg-old

6.7. Install and configure the latest version of PHP

Debian 12 comes with a new version of PHP, namely PHP 8.2. During the operating system upgrade, some PHP 8.2 packages will be installed, but to fully install PHP 8.2 and use it instead of PHP 7.4, which was the default version in Debian 11, you will have to install all the PHP 8.2 packages specified in the Install PHP chapter, and then configure PHP as described there. Therefore, follow all the steps described in the Install PHP chapter, up until the subchapter Install Memcached for object caching (since you don’t need to install and configure Memcached again).

After you have installed and configured PHP 8.2, you can uninstall all the php7.4 packages with:

apt-get purge php7.4*

Since the old versions of the WordPress plugin ‘Memcached Object Cache’ won’t work with PHP 8.2, to have all your WordPress websites interact correctly with the Memcached server, you will have to download the newest version of the ‘object-cache.php’ file from the official page of this plugin, and copy it inside the ‘wp-content’ directory of every WordPress website that you host on the server. Don’t forget to add a unique string of random characters generated with:

openssl rand -base64 48

at the top of each ‘object-cache.php’ file, like this:

if ( ! defined( 'WP_CACHE_KEY_SALT' ) ) {
	define( 'WP_CACHE_KEY_SALT', 'vkCi6QNmBT4drFMXpCIj57iEGte54CGO9yathz8fkdAsfP0k2gOU6lGdbLGHLqSh' );
You can send your questions and comments to: