During the last few days I have been upgrading all of my Debian systems from 10 (Buster) to 11 (Bullseye). In contrast to my many previous upgrades, this went less than smoothly (some of which was down to me rushing) and I encountered a few issues - this post serves just as a note of all of the issues and their resolution. My earlier post on checking Debian update readiness with Ansible is also related to this set of upgrades.

MAC address on Bridge devices

When I upgraded my server with 2 bonded (LAG) interfaces, the MAC address of the bridge interface changed from underlying interface’s MAC to a generated one causing the DHCP reservation to fail. I found others online with the same problem and used the suggested workaround of adding hwaddress XX:XX:XX:XX:XX:XX to (in my case) /etc/network/interfaces.d/br0 with the underlying interface’s (in my case the bond, which took its MAC address from the first physical interface) MAC address.

The new (generated) MAC is stable, according to the reference above, so I could replace the MAC address for this host everywhere else with the new br0 MAC but this was easier (less places to change it).

Upgrading PostgreSQL

This one was entirely my fault - when I did the first system, I forgot that Debian creates a new cluster for each major version of PostgreSQL. There is a command, provided by Debian that will do the upgrade. Normally the sequence is to run pg_dropcluster, to delete the newly installed cluster, then use pg_upgradecluster to migrate the old to the new:

# Migrating from Debian 10 (Buster, PostgreSQL 11) to 11 (Bullseye, PostgreSQL 13)
pg_dropcluster 13 main --stop
pg_upgradecluster 11 main

Then the old PostgreSQL packages can be removed. If, like me in a rush, you forget this and remove the packages and agree to let it remove the old PostgreSQL version’s data (which it explicitly checks with you in the removal process) you will find you have deleted your old databases. To recover from this position, I had to restore from the latest daily backup (created with ) as the postgres user:

# Goto today's backup - presuming today is a daily (not weekly or monthly) backup day
cd /srv/backups/database/postgres/$( date +%F )-daily
# Restore roles first - of will get errors
zcat globals.sql.gz | psql
# Restore the main postgres database
pg_restore -d postgres postgres.custom
# Restore all other databases - I did a couple of attempts to get this right, not sure if -c needs to be -C fon a clean cluster?
for file in *.custom; do if [[ "${file%.custom}" != "postgres" ]]; then pg_restore -c -d "${file%.custom}" "$file"; fi; done


In order to manage my VPS’ (limited) RAM, I have Amavis configured to only run one server process. This was working fine under Debian 10 (Buster) with version 2.11.0 but on Debian 11 (Bullseye), version 2.11.1 it appeared to be randomly stopping. It ran fine for a little while then died for no apparent reason, I eventually tracked down a bug against another project, Modoboa - Mail hosting made simple, reporting “Amavis crashed every 20 messages”. Long story short, Amavis no longer works with a single server process and a minimum of 2 is required for it to function due to how Debian’s systemd script is written:

PatTheMav For posterity’s sake: The reason why $max_servers set to 1 became an issue is because of how amavis’ Debian package is set up:

Systemd starts the service via ExecStart=/usr/sbin/amavisd-new foreground, which implicitly makes the service set daemonize to 0 and with only 1 server configured amavis will not fork but handle everything “in process” until the maximum amount of requests is reached and then quit.

Running with just 1 child process (which is forked anew after maximum amount of mails have been processed) requires the service to be run as a daemon, which Debian’s service configuration does not do by default.

To fix this I changed Amavis’ $max_servers to 2, from 1, in it’s configuration.


In Debian 10 (Buster), the python package (and associated python-*/-python packages) were Python version 2, with python3 providing Python version 3. In Debian 11 (Bullseye), the python package has been removed with python2 providing Python version 2 and python3 providing Python version 3 - although many packages with plain python in the name are still Python version 2.

What does this have to do with uWSGI? Well, the uwsgi-plugin-python (Python version 2) plugin I was using for my Python applications has been removed from Debian 11 (Bullseye) and now the only available Python plugin is the uwsgi-plugin-python3 - this plugin, in Debian at least, is called python3 not python internally by uWSGI’s configuration, so all application configuration files have to be updated.

Raspberry PI

My Raspberry PI 4, which I installed Debian Buster (10) on, gave me errors when running apt update (I’m trying to get out of the habit of using apt-get by default), after updating the sources files in /etc/apt/sources.list.d to Bullseye. I tracked it down to APT::Default-Release "buster"; in /etc/apt/apt.conf, which I presume came from the image I originally write to the SD card (when I was booting from that). Once that line was commented out, it upgraded to Debian 11 (Bullseye) without a problem.


BackupPC upgraded from version 3 (in Debian 10, Buster) to 4 (in Debian 11, Bullseye). This is a major upgrade, with the structure of its “pool” (where the backups are all stored) completely changed. Fortunately, (with the right configuration options) it supports using a v3 pool and v4 at the same time, and will dynamically migrate files from v3 to v4 as the are required by new backups.

I did encounter a few teething issues with the updated version, and even resorted to asking on the BackupPC-users mailing list.

The key problems were:

  1. I couldn’t find the XferLog links - it turned out I just had to scroll down a lot further to find them than in version 3
  2. Storage usage graphs were not appearing in version 4 - the code for the graphs was rewritten in version 4, and the new code is hard-coded to only show them to “Privileged” (i.e. administrator) users. Since these are purely read-only, informational, graphs I wonder what the developers’ rationale for making them admin-only is?
  3. The user I used to login cannot edit host configurations in version 4, but could with version 3. In the end, I could not figure out how this was working in the first place in version 3 - the only administrator user (and group) in the configuration file did not exist in the webserver’s authentication file, and the setting to allow users to edit configuration was set to 0 (i.e. false) - by rights this should not have been working before the upgrade.
  4. Although backups were succeeding, no new files were being backed up. I eventually tracked this down to --one-filesystem being added to the default rsync options, in version 4 - in version 3 it was fine to just backup / (with /proc and /sys given as excluded paths) and it would happily cross filesystem boundaries. I commented out --one-filesystem in the default options - I cannot imagine a situation where I actually want the backup tool not to cross filesystem boundaries.