Installing the Debian X32 port on a VM or real machine

X32 is an ABI for Linux that uses the x86-64 instruction set but 32-bit longs and pointers (this is called ILP32), thereby limiting the memory for a single process to 4 GiB. Compared to amd64 it offers significant memory savings and unlike plain i386 it can make use of all registers and extensions also available to 64-bit code.

Debian has an X32 port since 2013 but installing it isn't quite straightforward.
To follow this guide you'll need:
  • A Debian netinst CD for the amd64 architecture: https://www.debian.org/CD/netinst/

  • A computer or VM with x86-64 compatible CPU

  • An internet connection on the machine you are installing

Booting into rescue mode

In the boot menu, choose "Advanced Options" and select the "Rescue Mode" option.

Press TAB to edit the kernel command line and append the following option before booting: syscall.x32=y

Follow the menus until you're dropped to a shell ("Execute shell in installer environment").

Partitioning

Inside the shell run partman.

This starts the usual partitioning setup seen during Debian installation. Once it's done you will be dropped to the shell again.

Installing the system

Debootstrap

Debootstrap will install the system for us, but unfortunately there is no convenient way to get the debian-ports GPG keys into the rescue environment, so we'll just run with disabled signature checks.

debootstrap --no-check-gpg --arch=x32 unstable /target http://ftp.ports.debian.org/debian-ports/

You might notice that isc-dhcp-client fails to install at this step, this is not critical and will be dealt with later.

Chrooting

The next step is to enter the target system in a chroot:

mount --bind /dev /target/dev
mount --bind /proc /target/proc
mount --bind /sys /target/sys
chroot /target

First we'll do some basic system configuration.

The fstab you write needs to match the configured partition layout, in this example the layout is a single root partition (no /boot, no swap space). Using UUID=... notation here is also advisable but not fun to type out by hand (and irrelevant for a single-disk VM).

Here you should also uninstall the package that failed to install earlier.

passwd root
echo "/dev/sda1 / ext4 rw 0 1" >/etc/fstab

Repository configuration

The X32 repository does not include a Linux kernel package. This requires us to add the amd64 repository so we can install a kernel, but we need to make sure only linux-image but nothing else is pulled from there (via APT pinning).

Configure APT as follows:

apt install -y debian-ports-archive-keyring
cat >/etc/apt/sources.list
deb [arch=x32] http://ftp.ports.debian.org/debian-ports unstable main
deb [arch=amd64] http://deb.debian.org/debian unstable main
^D
cat >/etc/apt/preferences.d/amd64
Package: linux-image*:amd64
Pin: release b=amd64
Pin-Priority: 500

Package: *
Pin: release b=amd64
Pin-Priority: -1
^D
dpkg --add-architecture amd64
apt update

Kernel & Bootloader

Install the kernel and bootloader (GRUB):
export TERM=dumb
apt install -y linux-image-amd64 grub-pc

When asked by GRUB, select your primary hard drive (here: /dev/sda) as installation device.

Next, reconfigure grub to boot up the kernel with X32 enabled:
dpkg-reconfigure grub-pc

GRUB will ask for the Linux command line, which needs to be syscall.x32=y.

Cleaning up

The installation failure during debootstrap has left some files misconfigured.

The purpose of policy-rc.d and the modification to start-stop-daemon is that services are not started up during package installation. Since we're finished installing, these need to be undone:

rm /usr/sbin/policy-rc.d

mv /usr/sbin/start-stop-daemon.REAL /usr/sbin/start-stop-daemon

Lastly exit the chroot, umount the partitions and reboot:

umount /target/dev /target/proc /target/sys
umount /target

sync; reboot

Extras

Why does isc-dhcp-client fail to install?

isc-dhcp-client transitively depends on libmaxminddb, which requires pandoc during build.

pandoc itself is not available on x32 since one of its dependencies is also missing.

This is tracked as Debian bug #956041 and has been solved in February 2021.

Quick DHCP setup using systemd-networkd

Since isc-dhcp-client would provide the DHCP client we have a problem when we want to connect our freshly installed system to a network.

Fortunately, setting up DHCP with systemd-networkd is quite easy:

cat >/etc/systemd/network/eth.network
[Match]
Name=en*
[Network]
DHCP=ipv4
^D
systemctl enable --now systemd-networkd

Installing standard system software

tasksel can take care of installing software you'd usually find on a standard Debian installation (man pages, locale support, Perl, ...).

tasksel install standard

Same issue as before: isc-dhcp-client and bind9-related packages are uninstallable, so that requires some manual working around:

eval $(tasksel -t install standard | tr ' ' '\n' | egrep -v 'isc-dhcp-client|^bind9-' | tr '\n' ' ')

Material

Most parts of this guide are based on either of these two pages: