If you already have Debian 12 (bookworm) installed on your server, please skip this 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 lose 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 lose the settings stored in that file.
A reboot will be required to finish the upgrade and load the new kernel:
reboot
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_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
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' );
}