Steam in box86

From postmarketOS Wiki

This is a guide for setting up box86 and box64 inside of an Debian Distrobox container to run Steam games on arm64 devices.

box86/box64

box86 is an x86 emulator for arm32 Linux. box64 is an x86_64 emulator for arm64 Linux. Together, they can be used to run x86 and x86_64 applications on an arm64 Linux device. In the case of Steam, both 32- and 64-bit executables are used, and games can be either format, so we will need to set up a system with both box86 and box64 together. Because box86 runs purely in 32-bit mode, the host system needs a fairly complete arm32 system installed. The easiest way to do this is using Debian, as it has a full set of packages for both arm32 (armhf) and arm64 along with the ability to install both at the same time using multiarch. In order to use this setup on postmarketOS I will be using Distrobox to install a Debian arm64 image on top of postmarketOS that I can then enable the armhf architecture on and install the necessary libraries in both arm64 and armhf format.

Distrobox

Distrobox is a container manager designed to install and run persistent containers, optionally with root privileges and their own init system, on top of another distribution. It is available in postmarketOS. To install, simply run:

sudo apk add distrobox

Installing Debian image

Create the Debian Distrobox install by running:

distrobox create --image debian:latest --root

This will create a Debian container with root privileges. I tested with --init and without and the setup works either way, so I recommend not using --init as it adds unnecessary overhead.

Then you will need to enter the image by running:

distrobox enter --root debian-latest

This will go through the first-time setup which involves downloading all the packages and should eventually present you with a password prompt to create a password for your user account within the container. If it doesn't provide this prompt on the first run, run this command again and it should then give the password prompt.

After this, you should be inside of the Debian container.

Installing box86 and box64

Now that you're inside the container, you can prepare to install box86 and box64.

First, you will need to enable the armhf architecture in the dpkg package manager so that Debian can install 32-bit packages:

sudo dpkg --add-architecture armhf

Next, we will add repositories for installing box86:

sudo wget https://ryanfortner.github.io/box86-debs/box86.list -O /etc/apt/sources.list.d/box86.list
sudo wget -qO- https://ryanfortner.github.io/box86-debs/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box86-debs-archive-keyring.gpg 
sudo apt update
sudo apt install box86-sd845 -y

and box64:

sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
sudo wget -qO- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box64-debs-archive-keyring.gpg 
sudo apt update
sudo apt install box64 -y

Installing Steam

To install Steam, we download steam.deb from the Steam website and install it with apt install:

wget https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb
sudo apt install ./steam.deb -y

Finally, there are a bunch of extra dependencies we need to install for Steam to run properly. Install them with the following command:

sudo apt install libc6:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf libsm6:armhf libice6:armhf libgl1:armhf libxinerama1:armhf libxdamage1:armhf libibus-1.0-5 libncurses5:armhf libgl1-mesa-dri libgl1-mesa-dri:armhf libglu1-mesa libglu1-mesa:armhf libvulkan1 libvulkan1:armhf libcurl4 libcurl4:armhf -y

Running Steam

Before we can run any x86 or x86_64 executable, we have to register the binfmt handlers for box86 and box64. Since we're not using an init system in our container, we have to do this manually. Save the following script as box86-binfmt.sh:

# Set up binfmt handling for box86 and box64
# Adapted from QEMU script here: https://wiki.alpinelinux.org/wiki/How_to_make_a_cross_architecture_chroot

#!/bin/bash

i386_magic="\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00"
i386_mask="\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"

x86_64_magic="\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00"
x86_64_mask="\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"

echo "Registering box86 and box64 binaries in binfmt misc"

if [ ! -d /proc/sys/fs/binfmt_misc ]; then
    modprobe binfmt_misc || eend $? || return 1
fi

if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
    mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc >/dev/null || eend $? || return 1
fi

for arch in i386; do
    interpreter="/usr/local/bin/box86"
    magic=$(eval echo \$${arch}_magic)
    mask=$(eval echo \$${arch}_mask)

    echo ":box86:M::$magic:$mask:$interpreter:OCF" > /proc/sys/fs/binfmt_misc/register
done

for arch in x86_64; do
    interpreter="/usr/local/bin/box64"
    magic=$(eval echo \$${arch}_magic)
    mask=$(eval echo \$${arch}_mask)

    echo ":box64:M::$magic:$mask:$interpreter:OCF" > /proc/sys/fs/binfmt_misc/register
done

Then run it with:

sudo sh box86-binfmt.sh

Now you will be able to run x86 and x86_64 binaries just like native armhf and armhf binaries and they will run inside the respective box emulator. Every time you restart the container you will need to run this box86-binfmt.sh script to register the binfmt handlers before you can run Steam.

Finally, we can start Steam. In box86/64, starting Steam requires a few environment variables. I may set these up in a bashrc eventually, but for now you can start Steam like this:

STEAMOS=1 STEAM_RUNTIME=1 DBUS_FATAL_WARNINGS=0 steam