Upgrade a system to a different architecture (e.g.convert an old i386 system to x86_64). For more information about multi-architecture systems, see CategoryMultiarch.
This page focusses on switching from i386 to amd64, but the same approach should work for any pair of architectures that work on the same machine (e.g. armel and armhf).
Work in progress! Prefer to reinstall, or at least create a full backup before continuing.
ToDo: the crossgrader package entered Debian in 2020, using it should be documented on this page. See https://salsa.debian.org/crossgrading-team/debian-crossgrading/-/blob/master/INSTRUCTIONS.md.
Pre-requisites
Run the upgrade commands from a text mode console, not from within a graphical terminal. Run the commands locally, or at least within a tmux or screen session.
Use multiarch packages on your system and configure QEMU user emulation before you begin, so you can install and run packages for both architectures.
Steps
Install a kernel that supports both architectures in userland
# Check your pre-crossgrade kernel version:
uname -a | tee ~/pre-crossgrade-uname.txt
# Install your new kernel:
sudo apt install linux-image-amd64:amd64
# Reboot the machine:
sudo reboot
# After the reboot, check the kernel has actually changed:
cat ~/pre-crossgrade-uname.txt
uname -a
rm ~/pre-crossgrade-uname.txt
Make sure all packages are in sync between architectures
You need to upgrade first, or otherwise check all the versions of packages to be crossgraded in this step, to make sure all amd64/i386 packages are in version-sync, otherwise the cross-grade will break.
sudo apt clean
sudo apt upgrade
Crossgrade dpkg, tar and apt
Get all the packages needed to replace dpkg, tar and apt, then install them for the new architecture. It is changing dpkg that actually 'counts' for changing the default architecture.
tar (and other dependencies of apt and dpkg) must be replaced at the same time as dpkg and apt. The dependencies seem to be different in different Debian releases:
For buster: add just tar:amd64
For bullseye: add tar:amd64 apt-utils:amd64 perl-base:amd64
For ~2020-10 sid: add tar:amd64 apt:amd64 apt-utils:amd64 perl-base:amd64 libsystemd0:amd64
To install packages together, first download them with apt and then install all of them with dpkg.
# Remove files in /var/cache/apt/archives/
# to make the "*_amd64.deb" below do the right thing:
sudo apt clean
# Download packages you will definitely need:
sudo apt --download-only install dpkg:amd64 tar:amd64 apt:amd64
#
# Add extra packages for your version of Debian:
#
# bullseye:
sudo apt --download-only install apt-utils:amd64 perl-base:amd64
# bookworm:
sudo apt --download-only install dpkg:amd64 tar:amd64 apt:amd64 dpkg:i386- tar:i386- apt:i386-
# sid (tested 2020-10):
sudo apt --download-only install dpkg:amd64 tar:amd64 apt:amd64 libsystemd0:amd64
# Due to pre-dependencies you may have to run this more than once
# to unpack and configure all packages:
sudo dpkg --install /var/cache/apt/archives/*_amd64.deb
# Should print "amd64":
sudo dpkg --print-architecture
# Should print "i386":
sudo dpkg --print-foreign-architectures
sudo apt update
sudo apt upgrade
sudo apt full-upgrade
If you get errors about a missing libsystemd0 and can no longer run apt, you can still directly download libsystemd0, put the .deb in /var/cache/apt/archives/, and rerun dpkg --install /var/cache/apt/archives/*_amd64.deb. If apt upgrade still doesn't work, try apt install -f (might work without needing to type the 'Yes, do as I say').
Crossgrade all other architecture-dependent packages
If you got this far you are now effectively running amd64, but with mostly i386 packages.
Before a mass replacement from old to new architectures, if you have packages without installation candidates (from old releases), you may want to first try removing them with
sudo apt purge '?obsolete'
You can try to replace them with the corresponding amd64 packages. It should be possible to remove the i386 package and install the amd64 version instead. Not all libraries will necessarily support Multiarch, so they may not have a direct replacement.
Preserving the "auto" mark
Manually upgrading packages will clear the "automatically installed" flag for those packages that were automatically installed on i386.
If it works for you, the best way to do the swap that preserves all of dpkg and apt state regarding manual vs automatic package selection is:
# Get auto-installed packages:
sudo apt-mark showauto | sed -n -e's/:i386$//p' > auto-package-list
# Reinstall everything:
sudo apt install \
$(dpkg -l | awk '$1 ~ /^.i/ && $2 ~ /:i386$/ { sub(":i386", ""); print $2 }')
# Or for bookworm:
sudo apt install --allow-remove-essential \
$(dpkg -l | awk '$1 ~ /^.i/ && $2 ~ /:i386$/ { sub(":i386", ""); print $2; print $2 ":i386-" }')
# Reset the "auto" mark:
sudo xargs apt-mark auto < auto-package-list
You will have to type in 'Yes, do as I say' to get apt to do this, so make sure each package in the warning is actually going to get installed with the new architecture.
This method also has the advantage that if you have packages installed that are only available on i386, they will be kept installed rather than throwing an error about unavailable packages.
Notes 2020-10: I needed to edit the list to remove the pae kernel references and then use that edited list from a file for apt install. You will experience various errors regardless. I needed to for example manually dpkg -i bash and dash, symlink /bin/sh to the existing one a couple of times, and try again and again. Expect needing to do a lot of apt install -f, dpkg --configure -a, and manual dpkg -i from /var/cache/apt/archives/ and apt autoremove --purge (to remove replaced :i386 binaries). However using above and these notes I ended up with a functional system and there were big portions that just ran without interruptions.
Bulk crossgrade of all remaining i386 packages
Another more brutal way to do the swap is
dpkg --get-selections \
| sed -ne 's/:i386\(\t*install$\)/:amd64\1/p' \
| dpkg --set-selections
sudo apt -f install
You will have to type in 'Yes, do as I say' to get apt to do this.
Once the swap is complete, you can remove all the redundant libraries and drop the old architecture with
sudo apt purge $(dpkg -l | sed -ne 's/^.i \([^ ]*:i386\).*/\1/p')
sudo dpkg --remove-architecture i386
sudo apt update
Caveats and Known Problems
Caution with systemd
systemd may not like being cross-graded, possibly it is safer to cross-grade it from a liveCD. Make sure to cross-grade udev at the same time, otherwise various units will fail.
APT dependency resolver wants to revert apt itself
If the system had packages that depend on apt like apt-utils, it's possible run into a situation where apt -f install wants to revert apt itself to i386. Aborting and doing another operation apt autoremove will illustrate the reason better:
The following packages have unmet dependencies: apt-utils:i386 : Depends: apt:i386 (= 1.4.8) but it is not installed
In such a case, the solution is to temporarily remove apt-utils:i386 from the system, and install apt-utils afterwards. Note: this new apt-utils will be amd64, but once you switch apt to amd64, using the :amd64 suffix will not work.
Apt dependency resolver generates broken solutions
It might happen that apt's resolver emits an unworkable solution:
E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages. E: Unable to correct dependencies
In this case you can inspect what packages are marked as Broken and decide what to do:
sudo apt -o Debug::pkgProblemResolver=1 -f install
KDE
The KDE desktop environment creates the file ~/.config/Trolltech.conf, which contains locations of shared libararies and, more problematic, their architecture. This causes panel widgets to crash. The file can apparently be safely removed or renamed to fix these problems.
iamerican (and possibly others/similar)
Similar to KDE, some package(s) (e.g. iamerican on at least Debian 7.5) may have saved caches/hashes that need updating. E.g. echo foo | spell might generate:
/usr/bin/ispell: Illegal format hash table
corrected with e.g.:
sudo sh -c '(cd / && umask 022 && dpkg-reconfigure iamerican)'
which updates /var/lib/ispell/american.hash
See also
Announce by Guillem Jover, dpkg Maintainer (see "Cross-grading" at the bottom of the message)
Howto amd64 an i386 Debian installation with multiarch by Marc Haber
Crossgrading Debian in 2017 by Simon Richter
Upgrading Debian from 32-bit to 64-bit - AKA crossgrading from i386 to amd64 by anarcat
i386 to amd64 - Debian 7.5 from i386 to amd64, discussion + links to edited script(1) capture, etc., by Michael Paoli
- Articles by Jose M. Calhariz:
Migrate a 32-bit debian installation to 64-bit one (i386 to x86_64)
Migrate/Upgrade Debian 7 Wheezy GNU/Linux from 32 bit to 64 bit HowTo
Sample cross-grade script
The script below was written in 2015, and may not have been tested on any supported version of Debian. Consider using crossgrader instead.
#! /bin/bash
# scary script to crossgrade your debian machine between arches.
# usage crossgrade <final-architecture>
set -e
if [ -z "$1" ]; then
echo "Usage: crossgrade <architecture> (debian architecture to convert to)"
exit 1
fi
#validate arch
if ! TO=$(dpkg-architecture -qDEB_HOST_ARCH -a$1); then
echo "$1 is not a recognised architecture name"
exit 1
fi
FROM=$(dpkg --print-architecture)
echo "Crossgrading from $FROM to $TO"
#check for a compatible kernel
# should check $FROM and $TO harder
# allow for switching kernel over too to minimal one if requested?
case $TO in
amd64)
TO_KERN=amd64
;;
i386)
TO_KERN=amd64
;;
armhf)
TO_KERN=armhf
;;
armel)
TO_KERN=armhf
;;
arm64)
TO_KERN=arm64
;;
mips)
TO_KERN=mips64le
;;
mipsel)
TO_KERN=mips64le
;;
mips64le)
TO_KERN=mips64le
;;
ppc)
TO_KERN=ppc64el
;;
powerpc)
TO_KERN=ppc64el
;;
ppc64el)
TO_KERN=ppc64el
esac
dpkg --add-architecture $TO
# check that dpkg --print-foreign-architectures is $TO
apt update
apt upgrade
# Install a kernel capable to run the new architecture with the old
# architecture in userspace
KERNEL=$(uname -m)
echo "Current kernel arch is $KERNEL"
if [ "$KERNEL" != "$TO_KERN" ]; then
if apt install linux-image-$TO:$TO; then
echo "There should be a reboot here"
exit 1
#reboot
else
echo "kernel updating to linux-image-$TO:$TO failed"
fi
fi
echo Crossgrading dpkg and apt
apt clean
apt --download-only install dpkg:$TO apt:$TO tar:$TO
#check ever package to be installed is available in same version for amd64 if installed (multiarch sync is needed)
#for pkg in /var/cache/apt/archives/*_$TO.deb
#do
# file=$(basename $pkg)
# pkgname= ${file%%_.*}
# version= ${file##*._}
# if dpkg -l $($pkgname)
#done
#in practice this needs to run twice (do it more? is there a better way?)
if ! dpkg --install /var/cache/apt/archives/*_$TO.deb; then
dpkg --install /var/cache/apt/archives/*_$TO.deb
fi
test $(dpkg --print-architecture) = $TO
test $(dpkg --print-foreign-architectures | grep $FROM) = $FROM
echo "Yay! dpkg and apt crossgrade completed successfully"
echo "Updating core packages"
apt upgrade
apt full-upgrade
echo "Removing obsolete packages"
apt install aptitude:$TO
aptitude purge '?obsolete'
echo "Mass reinstalling $TO packages -- double check installed packages match warned-about packages"
apt install $(dpkg -l | grep '^.i.*:'"$FROM" | grep ":$FROM" | sed -e "s/:$FROM/:$TO/" | awk '{print $2}')
echo "Removing redundant libraries"
apt purge $(dpkg -l | grep '^.i.*:'"$FROM" | awk '{print $2}')
echo "Removing $FROM"
dpkg --remove-architecture "$FROM"
apt update
